Merge pull request #22645 from kaspth/parameters-only-deep-dup-hash-array

Only dup Ruby's Hash and Array.
This commit is contained in:
Matthew Draper 2015-12-18 07:34:02 +10:30
commit 84eba99ceb
2 changed files with 46 additions and 2 deletions

View File

@ -1,4 +1,5 @@
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 @@ module ActionController
# 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 @@ module ActionController
# <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 @@ module ActionController
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)

View File

@ -297,4 +297,32 @@ class ParametersPermitTest < ActiveSupport::TestCase
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