Skip to content
Browse files

Merge pull request #10784 from senny/10526_prevent_key_transformation

Prevent side effects in `Hash#with_indifferent_access`.
Conflicts:
	activesupport/CHANGELOG.md
  • Loading branch information...
1 parent 8eb6ea7 commit 72f7f94cec42a841a17ab112af27579fcb4d9920 @rafaelfranca rafaelfranca committed Jun 3, 2013
View
18 activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -91,7 +91,7 @@ def self.[](*args)
#
# This value can be later fetched using either +:key+ or +'key'+.
def []=(key, value)
- regular_writer(convert_key(key), convert_value(value))
+ regular_writer(convert_key(key), convert_value(value, for: :assignment))
end
alias_method :store, :[]=
@@ -231,7 +231,7 @@ def to_options!; self end
def to_hash
_new_hash= {}
each do |key, value|
- _new_hash[convert_key(key)] = convert_value(value, true)
+ _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
end
Hash.new(default).merge!(_new_hash)
end
@@ -241,12 +241,18 @@ def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end
- def convert_value(value, _convert_for_to_hash = false)
+ def convert_value(value, options = {})
if value.is_a? Hash
- _convert_for_to_hash ? value.to_hash : value.nested_under_indifferent_access
+ if options[:for] == :to_hash
+ value.to_hash
+ else
+ value.nested_under_indifferent_access
+ end
elsif value.is_a?(Array)
- value = value.dup if value.frozen?
- value.map! { |e| convert_value(e, _convert_for_to_hash) }
+ unless options[:for] == :assignment
+ value = value.dup
+ end
+ value.map! { |e| convert_value(e, options) }
else
value
end
View
7 activesupport/test/core_ext/hash_ext_test.rb
@@ -503,6 +503,13 @@ def test_lookup_returns_the_same_object_that_is_stored_in_hash_indifferent_acces
assert_equal [1], hash[:a]
end
+ def test_with_indifferent_access_has_no_side_effects_on_existing_hash
+ hash = {content: [{:foo => :bar, 'bar' => 'baz'}]}
+ hash.with_indifferent_access
+
+ assert_equal [:foo, "bar"], hash[:content].first.keys
+ end
+
def test_indifferent_hash_with_array_of_hashes
hash = { "urls" => { "url" => [ { "address" => "1" }, { "address" => "2" } ] }}.with_indifferent_access
assert_equal "1", hash[:urls][:url].first[:address]

0 comments on commit 72f7f94

Please sign in to comment.
Something went wrong with that request. Please try again.