Skip to content

Commit

Permalink
Bugfix: Correctly handle given in Array params
Browse files Browse the repository at this point in the history
Array parameters are handled as a parameter that opens a
scope with `type: Array`; `given` opens up a new scope, but
was always setting the type to Hash. This patch fixes that,
as well as correctly labeling the error messages associated
with array fields.
  • Loading branch information
rnubel committed May 5, 2017
1 parent c644607 commit 3d125cb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
34 changes: 18 additions & 16 deletions lib/grape/validations/params_scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,39 @@ def should_validate?(parameters)
return false if @optional && (params(parameters).blank? ||
any_element_blank?(parameters))

@dependent_on.each do |dependency|
if dependency.is_a?(Hash)
dependency_key = dependency.keys[0]
proc = dependency.values[0]
return false unless proc.call(params(parameters).try(:[], dependency_key))
elsif params(parameters).try(:[], dependency).blank?
return false
if @dependent_on && !params(parameters).is_a?(Array)
@dependent_on.each do |dependency|
if dependency.is_a?(Hash)
dependency_key = dependency.keys[0]
proc = dependency.values[0]
return false unless proc.call(params(parameters).try(:[], dependency_key))
elsif params(parameters).try(:[], dependency).blank?
return false
end
end
end if @dependent_on
end

return true if parent.nil?
parent.should_validate?(parameters)
end

# @return [String] the proper attribute name, with nesting considered.
def full_name(name)
def full_name(name, index: nil)
if nested?
# Find our containing element's name, and append ours.
"#{@parent.full_name(@element)}#{array_index}[#{name}]"
[@parent.full_name(@element), [@index || index, name].map(&method(:brackets))].compact.join
elsif lateral?
# Find the name of the element as if it was at the
# same nesting level as our parent.
@parent.full_name(name)
# Find the name of the element as if it was at the same nesting level
# as our parent. We need to forward our index upward to achieve this.
@parent.full_name(name, index: @index)
else
# We must be the root scope, so no prefix needed.
name.to_s
end
end

def array_index
"[#{@index}]" if @index.present?
def brackets(val)
"[#{val}]" if val
end

# @return [Boolean] whether or not this scope is the root-level scope
Expand Down Expand Up @@ -187,7 +189,7 @@ def new_lateral_scope(options, &block)
element: nil,
parent: self,
options: @optional,
type: Hash,
type: type == Array ? Array : Hash,
dependent_on: options[:dependent_on],
&block
)
Expand Down
23 changes: 23 additions & 0 deletions spec/grape/validations/params_scope_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,29 @@ def initialize(value)
end
end

context 'when validations are dependent on a parameter within an array param' do
before do
subject.params do
requires :foos, type: Array do
optional :foo_type, :baz_type
given :foo_type do
requires :bar
end
end
end
subject.post('/test') { declared(params).to_json }
end

it 'applies the constraint within each value' do
post '/test',
{ foos: [ { foo_type: 'a' }, { bar: 'not_needed', baz_type: 'c' } ] }.to_json,
{ 'CONTENT_TYPE' => 'application/json' }

expect(last_response.status).to eq(400)
expect(last_response.body).to eq('foos[0][bar] is missing')
end
end

context 'when validations are dependent on a parameter with specific value' do
# build test cases from all combinations of declarations and options
a_decls = %i(optional requires)
Expand Down

0 comments on commit 3d125cb

Please sign in to comment.