Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* [#2706](https://github.com/ruby-grape/grape/pull/2706): Refactor `ParamsScope#validates` and `ParamsDocumentation` around a frozen `Grape::Validations::ValidationsSpec` value object; the validations hash supplied by the DSL is no longer mutated and the helper chain becomes pure - [@ericproulx](https://github.com/ericproulx).
* [#2707](https://github.com/ruby-grape/grape/pull/2707): Tighten six guard conditions in `lib/` via De Morgan and `blank?`/`present?`/`include?` rewrites; no behaviour change - [@ericproulx](https://github.com/ericproulx).
* [#2709](https://github.com/ruby-grape/grape/pull/2709): Lift trailing `if/else` into guard clauses; tighten `Util::Lazy::ValueEnumerable` - [@ericproulx](https://github.com/ericproulx).
* [#2710](https://github.com/ruby-grape/grape/pull/2710): Tidy up `Grape::DeclaredParamsHandler` - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

#### Fixes
Expand Down
98 changes: 48 additions & 50 deletions lib/grape/declared_params_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,69 +50,67 @@ def declared_hash(passed_params, declared_params:, params_nested_path:, renamed_
end

def declared_hash_attr(passed_params, declared_param:, params_nested_path:, memo:, renamed_params:, route_params:)
if declared_param.is_a?(Hash)
declared_param.each_pair do |declared_parent_param, declared_children_params|
next unless @include_missing || passed_params.key?(declared_parent_param)

memo_key = build_memo_key(params_nested_path, declared_parent_param, renamed_params)
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new

params_nested_path_dup = params_nested_path.dup
params_nested_path_dup << declared_parent_param.to_s

memo[memo_key] = handle_passed_param(params_nested_path_dup, route_params:, has_passed_children: passed_children_params.any?) do
recursive_declared(
passed_children_params,
declared_params: declared_children_params,
params_nested_path: params_nested_path_dup,
renamed_params:,
route_params:
)
end
end
else
# If it is not a Hash then it does not have children.
# Find its value or set it to nil.
return unless @include_missing || (passed_params.respond_to?(:key?) && passed_params.key?(declared_param))

memo_key = build_memo_key(params_nested_path, declared_param, renamed_params)
passed_param = passed_params[declared_param]

params_nested_path_dup = params_nested_path.dup
params_nested_path_dup << declared_param.to_s

memo[memo_key] = passed_param || handle_passed_param(params_nested_path_dup, route_params:) do
passed_param
end
return declare_leaf(passed_params, declared_param:, params_nested_path:, memo:, renamed_params:, route_params:) unless declared_param.is_a?(Hash)

declared_param.each_pair do |parent, children|
declare_nested(passed_params, parent:, children:, params_nested_path:, memo:, renamed_params:, route_params:)
end
end

def build_memo_key(params_nested_path, declared_param, renamed_params)
rename_path = params_nested_path + [declared_param.to_s]
renamed_param_name = renamed_params[rename_path]
def declare_nested(passed_params, parent:, children:, params_nested_path:, memo:, renamed_params:, route_params:)
return unless @include_missing || passed_params.key?(parent)

memo_key = build_memo_key(params_nested_path, parent, renamed_params)
passed_children = passed_params[parent] || passed_params.class.new
nested_path = nested_path_for(params_nested_path, parent)

memo[memo_key] = handle_passed_param(nested_path, route_params:, has_passed_children: passed_children.any?) do
recursive_declared(
passed_children,
declared_params: children,
params_nested_path: nested_path,
renamed_params:,
route_params:
)
end
end

# The declared param has no children. Find its value or set it to nil.
def declare_leaf(passed_params, declared_param:, params_nested_path:, memo:, renamed_params:, route_params:)
return unless @include_missing || (passed_params.respond_to?(:key?) && passed_params.key?(declared_param))

memo_key = build_memo_key(params_nested_path, declared_param, renamed_params)
passed_param = passed_params[declared_param]

memo[memo_key] = passed_param || handle_passed_param(nested_path_for(params_nested_path, declared_param), route_params:) do
passed_param
end
end

def build_memo_key(params_nested_path, declared_param, renamed_params)
renamed_param_name = renamed_params[nested_path_for(params_nested_path, declared_param)]
param = renamed_param_name || declared_param
@stringify ? param.to_s : param.to_sym
end

def handle_passed_param(params_nested_path, route_params:, has_passed_children: false, &_block)
def nested_path_for(parent_path, key)
parent_path + [key.to_s]
end

def handle_passed_param(params_nested_path, route_params:, has_passed_children: false)
return yield if has_passed_children

key = params_nested_path[0]
key = params_nested_path.first
key += "[#{params_nested_path[1..].join('][')}]" if params_nested_path.size > 1

type = route_params.dig(key, :type)
has_children = route_params.keys.any? { |k| k != key && k.start_with?("#{key}[") }

if type == 'Hash' && !has_children
{}
elsif type == 'Array' || (type&.start_with?('[') && !type.include?(','))
[]
elsif type == 'Set' || type&.start_with?('#<Set', 'Set')
Set.new
else
yield
end
return yield if type.nil?

return {} if type == 'Hash' && route_params.keys.none? { |k| k != key && k.start_with?("#{key}[") }
return [] if type == 'Array' || (type.start_with?('[') && !type.include?(','))
return Set.new if type == 'Set' || type.start_with?('#<Set', 'Set')

yield
end
end
end
Loading