diff --git a/CHANGELOG.md b/CHANGELOG.md index 6140beae28..2693ea97b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Next Release #### Fixes * [#492](https://github.com/intridea/grape/pull/492): Don't allow to have nil value when a param is required and has a list of allowed values. - [@Antti](https://github.com/Antti) +* [#495](https://github.com/intridea/grape/pull/495): Fix `ParamsScope#params` for parameters nested inside arrays - [@asross](https://github.com/asross). 0.6.1 ===== diff --git a/lib/grape/validations.rb b/lib/grape/validations.rb index 7dd9a8d4e8..d079449c1b 100644 --- a/lib/grape/validations.rb +++ b/lib/grape/validations.rb @@ -102,7 +102,7 @@ def initialize(opts, &block) end def should_validate?(parameters) - return false if @optional && params(parameters).blank? + return false if @optional && params(parameters).all?(&:blank?) return true if parent.nil? parent.should_validate?(parameters) end @@ -133,7 +133,13 @@ def group(element, &block) def params(params) params = @parent.params(params) if @parent - params = params[@element] || {} if @element + if @element + if params.is_a?(Array) + params = params.map { |el| el[@element] || {} } + else + params = params[@element] || {} + end + end params end diff --git a/spec/grape/validations_spec.rb b/spec/grape/validations_spec.rb index 0f35268733..6c5302f21a 100644 --- a/spec/grape/validations_spec.rb +++ b/spec/grape/validations_spec.rb @@ -156,6 +156,49 @@ def app end end + context 'validation within arrays' do + before do + subject.params do + group :children do + requires :name + group :mother do + requires :name + end + end + end + subject.get '/within_array' do + 'within array works' + end + end + + it 'can handle new scopes within child elements' do + get '/within_array', children: [ + { name: 'John', mother: { name: 'Jane' } }, + { name: 'Joe', mother: { name: 'Josie' } } + ] + last_response.status.should == 200 + last_response.body.should == 'within array works' + end + + it 'errors when a parameter is not present' do + get '/within_array', children: [ + { name: 'Jim', mother: {} }, + { name: 'Job', mother: { name: 'Joy' } } + ] + last_response.status.should == 400 + last_response.body.should == 'children[mother][name] is missing' + end + + it 'safely handles empty arrays and blank parameters' do + get '/within_array', children: [] + last_response.status.should == 400 + last_response.body.should == 'children[name] is missing, children[mother][name] is missing' + get '/within_array', children: [name: 'Jay'] + last_response.status.should == 400 + last_response.body.should == 'children[mother][name] is missing' + end + end + context 'optional with a block' do before do subject.params do @@ -234,6 +277,20 @@ def app last_response.body.should == 'nested optional group works' end + it 'handles validation within arrays' do + get '/nested_optional_group', items: [key: 'foo'] + last_response.status.should == 400 + last_response.body.should == 'items[required_subitems][value] is missing' + + get '/nested_optional_group', items: [key: 'foo', required_subitems: { value: 'bar' }] + last_response.status.should == 200 + last_response.body.should == 'nested optional group works' + + get '/nested_optional_group', items: [key: 'foo', required_subitems: { value: 'bar' }, optional_subitems: { not_value: 'baz' }] + last_response.status.should == 400 + last_response.body.should == 'items[optional_subitems][value] is missing' + end + it 'adds to declared parameters' do subject.params do optional :items do