Skip to content

Commit

Permalink
Allow for multiple fields in load condition functions
Browse files Browse the repository at this point in the history
  • Loading branch information
rtalhouk committed Nov 22, 2023
1 parent 1c89068 commit 2ce0b6f
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 78 deletions.
80 changes: 47 additions & 33 deletions app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ func (c *AppConfig) checkForFieldSetDependencies(fieldSet *FieldSet) []error {
errs := []error{}

for _, loadCondition := range fieldSet.LoadConditions {
fieldSetKey, fieldKey := loadCondition.FieldDependency()
if fieldSetKey == "" && fieldKey == "" {
fieldSetKey, fieldKeys := loadCondition.FieldDependency()
if fieldSetKey == "" && len(fieldKeys) == 0 {
continue
}

Expand All @@ -495,15 +495,17 @@ func (c *AppConfig) checkForFieldSetDependencies(fieldSet *FieldSet) []error {
continue
}

_, found = fieldSetDependency.fieldMap[fieldKey]
if !found {
errs = append(
errs,
fmt.Errorf(
"field-set '%s' field-set dependency field not found: %s_%s",
fieldSet.Key, fieldSetKey, fieldKey,
),
)
for _, fieldKey := range fieldKeys {
_, found = fieldSetDependency.fieldMap[fieldKey]
if !found {
errs = append(
errs,
fmt.Errorf(
"field-set '%s' field-set dependency field not found: %s_%s",
fieldSet.Key, fieldSetKey, fieldKey,
),
)
}
}
}

Expand All @@ -523,9 +525,9 @@ func (c *AppConfig) checkForFieldDependencies(field *Field, parent *FieldSet) er

var found bool

fieldSetKey, fieldKey := loadCondition.FieldDependency()
fieldSetKey, fieldKeys := loadCondition.FieldDependency()

if fieldSetKey == "" && fieldKey == "" {
if fieldSetKey == "" && len(fieldKeys) == 0 {
continue
}

Expand All @@ -543,11 +545,13 @@ func (c *AppConfig) checkForFieldDependencies(field *Field, parent *FieldSet) er
}
}

if _, found = fieldSetDependency.fieldMap[fieldKey]; !found {
return fmt.Errorf(
"field-set '%s' field '%s' field-set field not found: %s_%s",
parent.Key, field.Key, fieldSetKey, fieldKey,
)
for _, fieldKey := range fieldKeys {
if _, found = fieldSetDependency.fieldMap[fieldKey]; !found {
return fmt.Errorf(
"field-set '%s' field '%s' field-set field not found: %s_%s",
parent.Key, field.Key, fieldSetKey, fieldKey,
)
}
}
}
}
Expand Down Expand Up @@ -648,14 +652,19 @@ func (c *AppConfig) shouldLoadFieldSet(fieldSet *FieldSet) (bool, error) {
break
}

conditionFieldSetKey, conditionFieldSetFieldKey := loadCondition.FieldDependency()
if conditionFieldSetKey != "" && conditionFieldSetFieldKey != "" {
fieldValue, err := c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
conditionFieldSetKey, conditionFieldSetFieldKeys := loadCondition.FieldDependency()
if conditionFieldSetKey != "" && len(conditionFieldSetFieldKeys) > 0 {
var err error
fieldValues := map[string]any{}

Check failure on line 658 in app_config.go

View workflow job for this annotation

GitHub Actions / lint

assignments should only be cuddled with other assignments (wsl)

for _, conditionFieldSetFieldKey := range conditionFieldSetFieldKeys {
fieldValues[conditionFieldSetFieldKey], err = c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
}
}

loadFieldSet, err = loadCondition.Load(fieldValue)
loadFieldSet, err = loadCondition.Load(fieldValues)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
}
Expand Down Expand Up @@ -686,18 +695,23 @@ func (c *AppConfig) shouldLoadField(field *Field, fieldSetKey string) (bool, err
break
}

conditionFieldSetKey, conditionFieldSetFieldKey := loadCondition.FieldDependency()
conditionFieldSetKey, conditionFieldSetFieldKeys := loadCondition.FieldDependency()
if conditionFieldSetKey == "" {
conditionFieldSetKey = fieldSetKey
}

if conditionFieldSetKey != "" && conditionFieldSetFieldKey != "" {
fieldValue, err := c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
if conditionFieldSetKey != "" && len(conditionFieldSetFieldKeys) > 0 {
var err error
fieldValues := map[string]any{}

Check failure on line 705 in app_config.go

View workflow job for this annotation

GitHub Actions / lint

assignments should only be cuddled with other assignments (wsl)

for _, conditionFieldSetFieldKey := range conditionFieldSetFieldKeys {
fieldValues[conditionFieldSetFieldKey], err = c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
}
}

loadField, err = loadCondition.Load(fieldValue)
loadField, err = loadCondition.Load(fieldValues)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
}
Expand Down Expand Up @@ -867,11 +881,11 @@ func (c *AppConfig) fieldHelpString(fields map[string]*fieldEntry, key string) s
}

for _, condition := range loadConditions {
fieldSetDependency, fieldDependency := condition.FieldDependency()
if fieldSetDependency != "" && fieldDependency != "" {
fieldSetDependency, fieldDependencies := condition.FieldDependency()
if fieldSetDependency != "" && len(fieldDependencies) > 0 {
builder.WriteString(spaceBuffer)
builder.WriteString(
fmt.Sprintf("Loading depends on field: '%s_%s'\n", fieldSetDependency, fieldDependency),
fmt.Sprintf("Loading depends on field: '%s_%s'\n", fieldSetDependency, fieldDependencies),
)
} else {
builder.WriteString(spaceBuffer)
Expand Down
48 changes: 24 additions & 24 deletions app_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ func TestAppConfigHelpString(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: stringFieldKey,
Condition: func(fieldValue any) (bool, error) {
val, ok := fieldValue.(string)
FieldKeys: []string{stringFieldKey},
Condition: func(fieldValues map[string]any) (bool, error) {
val, ok := fieldValues[stringFieldKey].(string)
if !ok {
return false, fmt.Errorf("unexpected field value type")
}
Expand Down Expand Up @@ -159,9 +159,9 @@ func TestAppConfig(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: "app",
FieldKey: "connect_sqlite",
Condition: func(fieldValue any) (bool, error) {
val, ok := fieldValue.(bool)
FieldKeys: []string{"connect_sqlite"},
Condition: func(fieldValues map[string]any) (bool, error) {
val, ok := fieldValues["connect_sqlite"].(bool)
if !ok {
return false, fmt.Errorf("unexpected field-type value")
}
Expand Down Expand Up @@ -342,8 +342,8 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: defaultFieldSetLoadAppOneKey,
Condition: func(fieldValue any) (bool, error) {
FieldKeys: []string{defaultFieldSetLoadAppOneKey},
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand All @@ -356,8 +356,8 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: defaultFieldSetLoadAppTwoKey,
Condition: func(fieldValue any) (bool, error) {
FieldKeys: []string{defaultFieldSetLoadAppTwoKey},
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand All @@ -370,7 +370,7 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
Condition: func(fieldValue any) (bool, error) {
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand Down Expand Up @@ -444,21 +444,21 @@ func TestAppConfigWithFieldLoadConditions(t *testing.T) {
fieldSetWithInternalFieldDependencies := bconf.FSB().Key(fieldSetOneKey).Fields(
bconf.FB().Key(fieldAKey).Type(bconf.String).Default("postgres").Create(),
bconf.FB().Key(fieldBKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
bconf.FB().Key(fieldCKey).Type(bconf.String).LoadConditions(
bconf.
FCB().
FieldKey(fieldAKey).
AddFieldKey(fieldAKey).
FieldSetKey(fieldSetOneKey).
Condition(func(val any) (bool, error) {
Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
bconf.FB().Key(fieldDKey).Type(bconf.String).Default("should_not_be_overridden").LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return false, nil
}).Create(),
).Create(),
Expand Down Expand Up @@ -490,15 +490,15 @@ func TestAppConfigWithFieldLoadConditions(t *testing.T) {
fieldSetWithMissingInternalFieldDependencies := bconf.FSB().Key(fieldSetThreeKey).Fields(
bconf.FB().Key(fieldFKey).Type(bconf.String).Create(),
bconf.FB().Key(fieldGKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
).Create()

fieldSetWithMissingExternalFieldDependencies := bconf.FSB().Key(fieldSetFourKey).Fields(
bconf.FB().Key(fieldAKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldSetKey("missing").FieldKey(fieldBKey).Condition(func(val any) (bool, error) {
bconf.FCB().FieldSetKey("missing").AddFieldKey(fieldBKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
Expand Down Expand Up @@ -583,8 +583,8 @@ func TestAppConfigAddField(t *testing.T) {
}

fieldMissingLoadCondition := bconf.FB().Key("field_missing_load_condition").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("missing_key").Condition(
func(val any) (bool, error) {
bconf.FCB().AddFieldKey("missing_key").Condition(
func(_ map[string]any) (bool, error) {
return true, nil
},
).Create(),
Expand Down Expand Up @@ -644,8 +644,8 @@ func TestAppConfigLoadFieldSet(t *testing.T) {
errs = appConfig.AddFieldSet(bconf.FSB().Key("bad_field_condition_conditional").Fields(
bconf.FB().Key("some_key").Type(bconf.String).Default("value").Create(),
).LoadConditions(
bconf.NewFieldConditionBuilder().FieldSetKey("default").FieldKey("field_key").Condition(
func(fieldValue any) (bool, error) {
bconf.NewFieldConditionBuilder().FieldSetKey("default").AddFieldKey("field_key").Condition(
func(_ map[string]any) (bool, error) {
return true, fmt.Errorf("condition error")
},
).Create(),
Expand Down Expand Up @@ -715,7 +715,7 @@ func TestAppConfigLoadField(t *testing.T) {
}

addedFieldC := bconf.FB().Key("field_c").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_b").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_b").Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create()
Expand All @@ -738,7 +738,7 @@ func TestAppConfigLoadField(t *testing.T) {
os.Setenv("STANDARD_D_FIELD_D", "expected_value")

addedFieldD := bconf.FB().Key("field_d").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_a").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_a").Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create()
Expand All @@ -762,7 +762,7 @@ func TestAppConfigLoadField(t *testing.T) {

// A test case for loading a field with a falsy field load condition
addedFieldE := bconf.FB().Key("field_e").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_a").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_a").Condition(func(_ map[string]any) (bool, error) {
return false, nil
}).Create(),
).Create()
Expand Down
16 changes: 8 additions & 8 deletions field_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package bconf
import "fmt"

type FieldCondition struct {
Condition func(fieldValue any) (bool, error)
Condition func(fieldValues map[string]any) (bool, error)
FieldSetKey string
FieldKey string
FieldKeys []string
}

func (c *FieldCondition) Clone() LoadCondition {
Expand All @@ -14,12 +14,12 @@ func (c *FieldCondition) Clone() LoadCondition {
return &clone
}

func (c *FieldCondition) FieldDependency() (fieldSetKey, fieldKey string) {
return c.FieldSetKey, c.FieldKey
func (c *FieldCondition) FieldDependency() (fieldSetKey string, fieldKeys []string) {
return c.FieldSetKey, c.FieldKeys
}

func (c *FieldCondition) Load(value any) (bool, error) {
return c.Condition(value)
func (c *FieldCondition) Load(values map[string]any) (bool, error) {
return c.Condition(values)
}

func (c *FieldCondition) Validate() []error {
Expand All @@ -29,8 +29,8 @@ func (c *FieldCondition) Validate() []error {
errs = append(errs, fmt.Errorf("field-set key required for field condition"))
}

if c.FieldKey == "" {
errs = append(errs, fmt.Errorf("field key required for field condition"))
if len(c.FieldKeys) == 0 {
errs = append(errs, fmt.Errorf("at least one field key required for field condition"))
}

return errs
Expand Down
6 changes: 3 additions & 3 deletions field_condition_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ func (b *FieldConditionBuilder) FieldSetKey(value string) *FieldConditionBuilder
return b
}

func (b *FieldConditionBuilder) FieldKey(value string) *FieldConditionBuilder {
func (b *FieldConditionBuilder) AddFieldKey(value string) *FieldConditionBuilder {
b.init()
b.condition.FieldKey = value
b.condition.FieldKeys = append(b.condition.FieldKeys, value)

return b
}

func (b *FieldConditionBuilder) Condition(value func(fieldValue any) (bool, error)) *FieldConditionBuilder {
func (b *FieldConditionBuilder) Condition(value func(fieldValues map[string]any) (bool, error)) *FieldConditionBuilder {
b.init()
b.condition.Condition = value

Expand Down
8 changes: 4 additions & 4 deletions field_condition_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ func TestFieldConditionBuilderKeys(t *testing.T) {
t.Fatalf("unexpected field-set key value '%s', expected '%s'", fsKey, fieldSetKey)
}

condition = bconf.FCB().FieldKey(fieldKey).Create()
if _, fKey := condition.FieldDependency(); fKey != fieldKey {
t.Fatalf("unexpected field key value '%s', expected '%s'", fKey, fieldKey)
condition = bconf.FCB().AddFieldKey(fieldKey).Create()
if _, fKeys := condition.FieldDependency(); fKeys[0] != fieldKey {
t.Fatalf("unexpected field key value '%s', expected '%s'", fKeys[0], fieldKey)
}
}

func TestFieldConditionBuilderCondition(t *testing.T) {
condition := func(fieldValue any) (bool, error) {
condition := func(_ map[string]any) (bool, error) {
return true, nil
}
fieldCondition := bconf.FCB().Condition(condition).Create()
Expand Down
8 changes: 4 additions & 4 deletions field_set_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ func TestFieldSetBuilderLoadConditions(t *testing.T) {
loadConditionFieldKey := "test_field_key"

fieldSet := bconf.FSB().LoadConditions(
bconf.FCB().FieldSetKey(loadConditionFieldSetKey).FieldKey(loadConditionFieldKey).Create(),
bconf.FCB().FieldSetKey(loadConditionFieldSetKey).AddFieldKey(loadConditionFieldKey).Create(),
).Create()

if len(fieldSet.LoadConditions) != 1 {
t.Fatalf("unexpected load-conditions length '%d', expected 1", len(fieldSet.LoadConditions))
}

fieldSetKey, fieldKey := fieldSet.LoadConditions[0].FieldDependency()
fieldSetKey, fieldKeys := fieldSet.LoadConditions[0].FieldDependency()
if fieldSetKey != loadConditionFieldSetKey {
t.Fatalf("unexpected field-set key '%s', expected '%s'", fieldSetKey, loadConditionFieldSetKey)
}

if fieldKey != loadConditionFieldKey {
t.Fatalf("unexpected field key '%s', expected '%s'", fieldKey, loadConditionFieldKey)
if fieldKeys[0] != loadConditionFieldKey {
t.Fatalf("unexpected field key '%s', expected '%s'", fieldKeys, loadConditionFieldKey)
}
}
Loading

0 comments on commit 2ce0b6f

Please sign in to comment.