mirror of https://github.com/rails/rails
Fix inconsistent results of params.deep_transform_keys (#50361)
* Fix inconsistent results of params.deep_transform_keys * fix: specs * fix: implements own deep_transform methods to ActionController::Parameters Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
This commit is contained in:
parent
278d6574cf
commit
32587c3bdd
|
@ -796,7 +796,7 @@ module ActionController
|
|||
# and from all nested hashes and arrays. The values are unchanged.
|
||||
def deep_transform_keys(&block)
|
||||
new_instance_with_inherited_permitted_status(
|
||||
@parameters.deep_transform_keys(&block)
|
||||
_deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -804,7 +804,7 @@ module ActionController
|
|||
# This includes the keys from the root hash and from all nested hashes and
|
||||
# arrays. The values are unchanged.
|
||||
def deep_transform_keys!(&block)
|
||||
@parameters.deep_transform_keys!(&block)
|
||||
@parameters = _deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -1042,6 +1042,46 @@ module ActionController
|
|||
end
|
||||
end
|
||||
|
||||
def _deep_transform_keys_in_object(object, &block)
|
||||
case object
|
||||
when Hash
|
||||
object.each_with_object(self.class.new) do |(key, value), result|
|
||||
result[yield(key)] = _deep_transform_keys_in_object(value, &block)
|
||||
end
|
||||
when Parameters
|
||||
if object.permitted?
|
||||
object.to_h.deep_transform_keys(&block)
|
||||
else
|
||||
object.to_unsafe_h.deep_transform_keys(&block)
|
||||
end
|
||||
when Array
|
||||
object.map { |e| _deep_transform_keys_in_object(e, &block) }
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
def _deep_transform_keys_in_object!(object, &block)
|
||||
case object
|
||||
when Hash
|
||||
object.keys.each do |key|
|
||||
value = object.delete(key)
|
||||
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
|
||||
end
|
||||
object
|
||||
when Parameters
|
||||
if object.permitted?
|
||||
object.to_h.deep_transform_keys!(&block)
|
||||
else
|
||||
object.to_unsafe_h.deep_transform_keys!(&block)
|
||||
end
|
||||
when Array
|
||||
object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
def specify_numeric_keys?(filter)
|
||||
if filter.respond_to?(:keys)
|
||||
filter.keys.any? { |key| /\A-?\d+\z/.match?(key) }
|
||||
|
|
|
@ -124,6 +124,25 @@ class ParametersMutatorsTest < ActiveSupport::TestCase
|
|||
assert_predicate @params.deep_transform_keys! { |k| k }, :permitted?
|
||||
end
|
||||
|
||||
test "deep_transform_keys! transforms nested keys" do
|
||||
@params.permit!
|
||||
@params.deep_transform_keys!(&:upcase)
|
||||
|
||||
expected_hash = { "PERSON" => { "AGE" => "32", "NAME" => { "FIRST" => "David", "LAST" => "Heinemeier Hansson" }, "ADDRESSES" => [{ "CITY" => "Chicago", "STATE" => "Illinois" }] } }
|
||||
assert_equal @params.to_hash, expected_hash
|
||||
end
|
||||
|
||||
test "deep_transform_keys transforms nested keys" do
|
||||
original_hash = @params.to_unsafe_h
|
||||
@params.permit!
|
||||
new_params = @params.deep_transform_keys(&:upcase)
|
||||
|
||||
assert_equal @params.to_hash, original_hash
|
||||
|
||||
expected_hash = { "PERSON" => { "AGE" => "32", "NAME" => { "FIRST" => "David", "LAST" => "Heinemeier Hansson" }, "ADDRESSES" => [{ "CITY" => "Chicago", "STATE" => "Illinois" }] } }
|
||||
assert_equal new_params.to_hash, expected_hash
|
||||
end
|
||||
|
||||
test "deep_transform_keys! retains unpermitted status" do
|
||||
assert_not_predicate @params.deep_transform_keys! { |k| k }, :permitted?
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue