diff options
author | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-06-18 21:54:43 -0300 |
---|---|---|
committer | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-06-18 21:54:43 -0300 |
commit | 27411a7c8d1c184876b1cb40ecdd07772551e6dd (patch) | |
tree | 92fd560b75709595a3fa6591c5fe4689067d8227 /activesupport | |
parent | 32c65d8da3fd28f8577bc23695846d47cdaac6fb (diff) | |
parent | 808592bae2b83ced018f16d576d41a0059ed302a (diff) | |
download | rails-27411a7c8d1c184876b1cb40ecdd07772551e6dd.tar.gz rails-27411a7c8d1c184876b1cb40ecdd07772551e6dd.tar.bz2 rails-27411a7c8d1c184876b1cb40ecdd07772551e6dd.zip |
Merge branch 'hash_with_indifferent_access_fix'
The problem:
Accessing a HashWithIndifferentAccess does not return the the same object
that is stored in the hash (i.e. equal?) causing unexpected results:
hash = HashWithIndifferentAccess.new {|h, k| h[k] = []}
hash[:a] << 1 # => [1]
hash[:a] # => [], expected [1]
The cause:
When a block is provided to generate default values the generated values
are duped if they are arrays. The duped value is stored in the hash but
the original value is returned when the hash is accessed.
The fix:
The duping is there for allowing frozen arrays containing hashes to be
modified. The fix restricts the duping to this case. Note that if default
function generates a frozen array an error will be raised on assignment
before and after the patch.
Closes #3811
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/hash_with_indifferent_access.rb | 3 | ||||
-rw-r--r-- | activesupport/test/core_ext/hash_ext_test.rb | 7 |
2 files changed, 9 insertions, 1 deletions
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 6e1c0da991..3e6c8893e9 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -164,7 +164,8 @@ module ActiveSupport if value.is_a? Hash value.nested_under_indifferent_access elsif value.is_a?(Array) - value.dup.replace(value.map { |e| convert_value(e) }) + value = value.dup if value.frozen? + value.map! { |e| convert_value(e) } else value end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 5d422ce5ad..4dc9f57038 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -457,6 +457,13 @@ class HashExtTest < ActiveSupport::TestCase assert_equal '1234', roundtrip.default end + def test_lookup_returns_the_same_object_that_is_stored_in_hash_indifferent_access + hash = HashWithIndifferentAccess.new {|h, k| h[k] = []} + hash[:a] << 1 + + assert_equal [1], hash[:a] + 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] |