aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-06-18 21:54:43 -0300
committerCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-06-18 21:54:43 -0300
commit27411a7c8d1c184876b1cb40ecdd07772551e6dd (patch)
tree92fd560b75709595a3fa6591c5fe4689067d8227 /activesupport
parent32c65d8da3fd28f8577bc23695846d47cdaac6fb (diff)
parent808592bae2b83ced018f16d576d41a0059ed302a (diff)
downloadrails-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.rb3
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb7
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]