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

Support fail_fast param validation option #1499

Merged
merged 8 commits into from
Oct 5, 2016

Conversation

dgasper
Copy link
Contributor

@dgasper dgasper commented Sep 28, 2016

#1423
This change will enable

params do
  required :beer, fail_fast: true
  required :wine
end

which will result in skipping of subsequent validation checks if a fail_fast required or optional fail validation.

@dgasper dgasper force-pushed the fail-fast-on-param-validation branch from 18c27b5 to 32de18e Compare September 28, 2016 15:01
@@ -140,9 +140,13 @@ def require_optional_fields(context, opts)
end

def validate_attributes(attrs, opts, &block)
# check fail_fast flag
fail_fast = opts.delete(:fail_fast) || false
Copy link
Member

Choose a reason for hiding this comment

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

You should not be modifying opts being passed in here, combine the clone below.

@@ -1355,6 +1355,23 @@ subject.rescue_from Grape::Exceptions::ValidationErrors do |e|
end
```

Grape returns all validation and coercion errors found by default. To skip all subsequent validation checks when a specific param is found invalid, use `fail_fast: true`.
For example:
Copy link
Member

Choose a reason for hiding this comment

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

Maybe space things up a bit. Minor.

required :wine
end
```
will not check if `:wine` is present unless it finds `:beer`. The result of empty params would be a single `Grape::Exceptions::ValidationErrors` error.
Copy link
Member

Choose a reason for hiding this comment

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

I think a lot of grape examples try to make full sentences, so prefer "The following example will not ..." to having "For example: [code] will not".

@@ -201,7 +205,7 @@ def configure_declared_params
end
end

def validates(attrs, validations)
def validates(attrs, validations, fail_fast = false)
Copy link
Member

Choose a reason for hiding this comment

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

I think the argument should be an options hash here, so we can make it extensible for the future. So def validates(attrs, validations, opts = {}).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@@ -10,10 +10,11 @@ class Base
# @param options [Object] implementation-dependent Validator options
# @param required [Boolean] attribute(s) are required or optional
# @param scope [ParamsScope] parent scope for this Validator
def initialize(attrs, options, required, scope)
def initialize(attrs, options, required, fail_fast, scope)
Copy link
Member

@dblock dblock Sep 30, 2016

Choose a reason for hiding this comment

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

Should fail_fast be rolled into one of these existing params? I am worried about custom validators other people built.

Copy link
Contributor Author

@dgasper dgasper Oct 3, 2016

Choose a reason for hiding this comment

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

@dblock I've thought about it. It could be a part of the scope, but I am not sure if it is the best place for validation options. Thoughts?

I've changed the constructor to the following to keep existing custom validators working.
def initialize(attrs, options, required, scope, opts = {})

@dblock
Copy link
Member

dblock commented Sep 30, 2016

This is excellent. Most of my comments are small implementation-related things, I'd like fail_fast to roll in as yet another option on the validator rather than its own big kind of thing. I am sure we'll have future other options.

@@ -140,9 +140,14 @@ def require_optional_fields(context, opts)
end

def validate_attributes(attrs, opts, &block)
Copy link
Member

Choose a reason for hiding this comment

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

Have you tried to do this?

def validate_attributes(attrs, validations, opts = {}, &block)

This way there wouldn't be any reason to do the selection below.

Copy link
Member

Choose a reason for hiding this comment

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

Either way this seems to be a bit too much future-proof ;)

validations = opts.clone
validations[:type] ||= Array if block

options = {}
options[:fail_fast] = validations.delete(:fail_fast)

Copy link
Member

@dblock dblock Oct 3, 2016

Choose a reason for hiding this comment

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

... which begs the question, why is fail_fast so special? Why does it need to be split at all? Why can't it just be @fail_fast = validations[:fail_fast] and not pass anything more around?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Then I would have to split the options here, no?

Hmm, I guess I got a bit carried away with the future other options idea :)

In my opinion, the difference is that the rest of the validations refer to a specific validation type with options whereas fail_fast (and possible future validation options) influences the validation process across multiple validations.

But I could be wrong. I just dove into grape code for the first time :)

Copy link
Member

Choose a reason for hiding this comment

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

Try to make it simpler for now, if not splitting is less code, we should go with that.

@dblock
Copy link
Member

dblock commented Oct 5, 2016

This is better. Merging.

@dblock dblock merged commit d734415 into ruby-grape:master Oct 5, 2016
@dgasper dgasper deleted the fail-fast-on-param-validation branch October 7, 2016 13:23
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.

2 participants