Skip to content

Commit

Permalink
Add all_or_none validator
Browse files Browse the repository at this point in the history
  • Loading branch information
loveltyoic committed Nov 7, 2014
1 parent b7199a0 commit d59e8b0
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
0.9.1 (Next)
============

* [#803](https://github.com/intridea/grape/pull/803): Add `all_or_none_of` parameter validator.- [@loveltyoic](https://github.com/loveltyoic).
* [#774](https://github.com/intridea/grape/pull/774): Extended `mutually_exclusive`, `exactly_one_of`, `at_least_one_of` to work inside any kind of group: `requires` or `optional`, `Hash` or `Array` - [@ShPakvel](https://github.com/ShPakvel).
* [#743](https://github.com/intridea/grape/pull/743): Added `allow_blank` parameter validator to validate non-empty strings - [@elado](https://github.com/elado).
* [#745](https://github.com/intridea/grape/pull/745): Removed `atom+xml`, `rss+xml`, and `jsonapi` content-types - [@akabraham](https://github.com/akabraham).
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,20 @@ params do
end
```

#### Nested `mutually_exclusive`, `exactly_one_of`, `at_least_one_of`
#### `all_or_none_of`

Parameters can be defined as 'all_or_none_of', ensuring that all or none of parameters gets selected.

```ruby
params do
optional :beer
optional :wine
optional :juice
all_or_none_of :beer, :wine, :juice
end
```

#### Nested `mutually_exclusive`, `exactly_one_of`, `at_least_one_of`, `all_or_none_of`

All of these methods can be used at any nested level.

Expand All @@ -666,6 +679,11 @@ params do
optional :icecream
mutually_exclusive :cake, :icecream
end
optional :recipe do
optional :oil
optional :meat
all_or_none_of :oil, :meat
end
end
```

Expand Down
1 change: 1 addition & 0 deletions lib/grape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,6 @@ class API
require 'grape/validations/validators/regexp'
require 'grape/validations/validators/values'
require 'grape/validations/params_scope'
require 'grape/validations/validators/all_or_none'

require 'grape/version'
1 change: 1 addition & 0 deletions lib/grape/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ en:
mutual_exclusion: 'are mutually exclusive'
at_least_one: 'are missing, at least one parameter must be provided'
exactly_one: 'are missing, exactly one parameter must be provided'
all_or_none: 'provide all or none of parameters'

20 changes: 20 additions & 0 deletions lib/grape/validations/validators/all_or_none.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Grape
module Validations
require 'grape/validations/validators/multiple_params_base'
class AllOrNoneOfValidator < MultipleParamsBase
def validate!(params)
super
if scope_requires_params && only_subset_present
raise Grape::Exceptions::Validation, params: all_keys, message_key: :all_or_none
end
params
end

private

def only_subset_present
scoped_params.any? { |resource_params| keys_in_common(resource_params).length > 0 && keys_in_common(resource_params).length < attrs.length }
end
end
end
end
61 changes: 61 additions & 0 deletions spec/grape/validations/validators/all_or_none_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require 'spec_helper'

describe Grape::Validations::AllOrNoneOfValidator do
describe '#validate!' do
let(:scope) do
Struct.new(:opts) do
def params(arg)
arg
end

def required?; end
end
end
let(:all_or_none_params) { [:beer, :wine, :grapefruit] }
let(:validator) { described_class.new(all_or_none_params, {}, false, scope.new) }

context 'when all restricted params are present' do
let(:params) { { beer: true, wine: true, grapefruit: true } }

it 'does not raise a validation exception' do
expect(validator.validate!(params)).to eql params
end

context 'mixed with other params' do
let(:mixed_params) { params.merge!(other: true, andanother: true) }

it 'does not raise a validation exception' do
expect(validator.validate!(mixed_params)).to eql mixed_params
end
end
end

context 'when none of the restricted params is selected' do
let(:params) { { somethingelse: true } }

it 'does not raise a validation exception' do
expect(validator.validate!(params)).to eql params
end
end

context 'when only a subset of restricted params are present' do
let(:params) { { beer: true, grapefruit: true } }

it 'raises a validation exception' do
expect {
validator.validate! params
}.to raise_error(Grape::Exceptions::Validation)
end
context 'mixed with other params' do
let(:mixed_params) { params.merge!(other: true, andanother: true) }

it 'raise a validation exception' do
expect {
validator.validate! params
}.to raise_error(Grape::Exceptions::Validation)
end
end
end

end
end

0 comments on commit d59e8b0

Please sign in to comment.