Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

schema: AnyOf FieldComparator implementation + #185 #216

Merged
merged 4 commits into from
Apr 4, 2019

Conversation

smyrman
Copy link
Collaborator

@smyrman smyrman commented Dec 11, 2018

This PR groups a few commits that does the following things in the schema package:

Copy of commit messages (latest first):

commit 1d4ba96 (origin/smyrman/anyof-cmp)
Author: Sindre Røkenes Myren sindre@searis.no
Date: Tue Dec 11 22:08:15 2018 +0100

travis: fix go modules bug

Travis is running pre-scripts to go get everything without go modules
enabled. Moving environment variable to `env` section.

There was a typo in the scripts section when setting GO111MODULE.

commit 7ed6b21
Author: Sindre Røkenes Myren sindre@searis.no
Date: Tue Dec 11 01:40:30 2018 +0100

schema: Allow AnyOf to implement FieldComparator

This changes the interface of FieldComparator so that it's possible for
FieldValidator types to determine, either run-time or compile-time, if
the validator is comparable.

AnyOf has been modified to Allow comparisons if one of it's
sub-validators allows it.

Changes the comparable types Float, Integer, AnyOf and Time to test only
the public interface; testing the private interface gives little value,
as it should be allowed to change without test updates.

commit 749c6a3
Author: Sindre Røkenes Myren sindre@searis.no
Date: Tue Dec 11 01:30:47 2018 +0100

schema: Let AnyOf/AllOf implement FieldGetter

Lets AnyOf and AllOf implement the FieldGetter interface.

commit 52c1b21
Author: Sindre Røkenes Myren sindre@searis.no
Date: Tue Dec 11 01:29:38 2018 +0100

schema: better errors for AnyOf/AllOf + cleanups

AnyOf and AllOf have received better error messages and doc-strings.
They have also been changed so that they will accept any value if there
are no members.

Clean up mergeFieldErrors to be easer to read; Go allows appending to
nil slice and expansion of slices in append, so there is no need for
the if branch and nested for-loop that was there before.

Simplify error handling in Object.Validate slightly. Moves the ErrorMap
type from object.go to errors.go and add some helper methods.

@smyrman smyrman force-pushed the smyrman/anyof-cmp branch 6 times, most recently from 7156c2d to 04e1027 Compare December 11, 2018 14:43
schema/anyof.go Outdated Show resolved Hide resolved
@smyrman smyrman force-pushed the smyrman/anyof-cmp branch 3 times, most recently from 3ebdaa7 to 1d4ba96 Compare December 11, 2018 21:28
@smyrman smyrman changed the title WIP: Smyrman/anyof cmp schema: schema.AnyOf FieldComparator + schema.AnyOf/schema.AllOf FieldGetter Dec 11, 2018
@smyrman smyrman changed the title schema: schema.AnyOf FieldComparator + schema.AnyOf/schema.AllOf FieldGetter schema: AnyOf FieldComparator implementation + #185 Dec 11, 2018
@smyrman smyrman requested a review from rs December 11, 2018 21:34
@smyrman
Copy link
Collaborator Author

smyrman commented Dec 11, 2018

@rs / @Dragomir-Ivanov, this is now ready for review.

Copy link
Contributor

@Dragomir-Ivanov Dragomir-Ivanov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except couple of code comments, LGTM.

schema/anyof_test.go Show resolved Hide resolved
schema/error.go Show resolved Hide resolved
@smyrman
Copy link
Collaborator Author

smyrman commented Dec 19, 2018

Rebased just now. @rs - do you have some time to review this?

schema/error.go Outdated
// Add adds an error to e and returns a new slice. If err is ErrorSlice, it is
// extended so that all the elements in err are apppended to e. If err is nil,
// then no error is appended. Note that calling Add on a nil slice is valid.
func (e ErrorSlice) Add(err error) ErrorSlice {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it works the same way as append, why not calling this method Append instead of Add?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

schema/error.go Outdated
}

// Extend copies all errors from err to e.
func (e ErrorMap) Extend(err ErrorMap) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be called Merge?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

schema/error.go Outdated
}

// Tidy returns an un-typed nil if e is empty, and an ErrorMap otherwise.
func (e ErrorMap) Tidy() error {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a strange API. Why do you need that? Couldn't we just expose a Len method and let the caller do what's appropriate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it's strange. Will change it. Len could work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

schema/object.go Outdated
var errMap ErrorMap
errMap = errs
return nil, errMap
if err := ErrorMap(errs).Tidy(); err != nil {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my comment above, I would find it easier to read if it was:

if len(errs) > 0 {
    return nil, ErrorMap(errs)
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@smyrman
Copy link
Collaborator Author

smyrman commented Mar 5, 2019

@rs, apologies for my very slow response on this one. I have now updated the PR with your suggested changes.

@Dragomir-Ivanov
Copy link
Contributor

Nice work @smyrman . Everything looks good, however I find it strange when we get the first lessFunc for schema.AnyOf. Is this right? It seems that shema.AnyOf is mainly used for shema.AnyOf{shema.Null, shema.XXX}. Can't we just add a field type nullable, and fix this?

@smyrman
Copy link
Collaborator Author

smyrman commented Mar 5, 2019

We have many use-case for schema.AnyOff besides shema.AnyOf{shema.Null, shema.XXX}, but the place where we need the less function to be implemented is indeed such cases.

Here are some examples of what we have (including some custom FieldValidators):

Validator: &schema.AnyOf{
	&schema.Null{},
	&rsc.Duration{Min: 2 * time.Millisecond, Max: 365 * 24 * time.Hour},
}
Validator: &schema.AnyOf{
	&schema.Null{},
	rsc.UTCTruncTime{Truncate: time.Hour * 24},
}

But even if we removed the Null type and added a Nullable filed (for convenience or as a short-hand), it would still be completely valid to define a schema like this:

Validator: &schema.AnyOf{
	&schema.Interger{Boundaries:&schema.Boundaries{Min:-5,Max:0}},
	&schema.Interger{Boundaries:&schema.Boundaries{Min:5,Max:10}},
}

Weird perhaps, but valid.

I think it would be good to aim for feature completeness in what's supported for AnyOf, AllOf so that they are more useful and diverse.

I am happy to discuss if adding the LessFunc has any unwanted side-effects that would be best to avoid.

AnyOf and AllOf have received better error messages and doc-strings.
They have also been changed so that they will accept any value if there
are no members.

Clean up mergeFieldErrors to be easer to read; Go allows appending to
nil slice and expansion of slices in append, so there is no need for
the if branch and nested for-loop that was there before.

Simplify error handling in Object.Validate slightly. Moves the ErrorMap
type from object.go to errors.go and add some helper methods.
Lets AnyOf and AllOf implement the FieldGetter interface.
This changes the interface of FieldComparator so that it's possible for
FieldValidator types to determine, either run-time or compile-time, if
the validator is comparable.

AnyOf has been modified to Allow comparisons if one of it's
sub-validators allows it.

Changes the comparable types Float, Integer, AnyOf and Time to test only
the public interface; testing the private interface gives little value,
as it should be allowed to change without test updates.
Travis is running pre-scripts to go get everything without go modules
enabled. Moving environment variable to `env` section.

There was a typo in the scripts section when setting GO111MODULE.
@smyrman
Copy link
Collaborator Author

smyrman commented Mar 6, 2019

rebased on master (no new changes)

@smyrman
Copy link
Collaborator Author

smyrman commented Apr 4, 2019

thx 🙇

@smyrman smyrman merged commit 552d179 into master Apr 4, 2019
@smyrman smyrman deleted the smyrman/anyof-cmp branch April 4, 2019 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

schema: Let AnyOf/AllOf implement the FieldGetter interface
3 participants