提交 4b46c5ce 编写于 作者: K Kasper Timm Hansen

Only dup Ruby's Hash and Array.

When calling `to_h` on an `ActionController::Parameters` instance it would
`deep_dup` its internal parameters.

This inadvertently called `dup` on a passed Active Record model which would
create new models. Fix by only dupping Ruby's Arrays and Hashes.
上级 623c3706
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/transform_values'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/string/filters'
require 'active_support/rescuable'
......@@ -175,7 +176,7 @@ def ==(other_hash)
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
def to_h
if permitted?
@parameters.deep_dup
convert_parameters_to_hashes(@parameters)
else
slice(*self.class.always_permitted_parameters).permit!.to_h
end
......@@ -185,7 +186,7 @@ def to_h
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> representation of this
# parameter.
def to_unsafe_h
@parameters.deep_dup
convert_parameters_to_hashes(@parameters)
end
alias_method :to_unsafe_hash, :to_unsafe_h
......@@ -594,6 +595,21 @@ def new_instance_with_inherited_permitted_status(hash)
end
end
def convert_parameters_to_hashes(value)
case value
when Array
value.map { |v| convert_parameters_to_hashes(v) }
when Hash
value.transform_values do |v|
convert_parameters_to_hashes(v)
end.with_indifferent_access
when Parameters
value.to_h
else
value
end
end
def convert_hashes_to_parameters(key, value)
converted = convert_value_to_parameters(value)
@parameters[key] = converted unless converted.equal?(value)
......
......@@ -297,4 +297,32 @@ def assert_filtered_out(params, key)
assert @params.to_h.is_a? ActiveSupport::HashWithIndifferentAccess
assert_not @params.to_h.is_a? ActionController::Parameters
end
test "to_h only deep dups Ruby collections" do
company = Class.new do
attr_reader :dupped
def dup; @dupped = true; end
end.new
params = ActionController::Parameters.new(prem: { likes: %i( dancing ) })
assert_equal({ 'prem' => { 'likes' => %i( dancing ) } }, params.permit!.to_h)
params = ActionController::Parameters.new(companies: [ company, :acme ])
assert_equal({ 'companies' => [ company, :acme ] }, params.permit!.to_h)
assert_not company.dupped
end
test "to_unsafe_h only deep dups Ruby collections" do
company = Class.new do
attr_reader :dupped
def dup; @dupped = true; end
end.new
params = ActionController::Parameters.new(prem: { likes: %i( dancing ) })
assert_equal({ 'prem' => { 'likes' => %i( dancing ) } }, params.to_unsafe_h)
params = ActionController::Parameters.new(companies: [ company, :acme ])
assert_equal({ 'companies' => [ company, :acme ] }, params.to_unsafe_h)
assert_not company.dupped
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册