diff options
Diffstat (limited to 'activesupport')
5 files changed, 35 insertions, 5 deletions
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index aad4b61e16..c2a6476604 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -9,4 +9,16 @@ class Hash def with_indifferent_access ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self) end + + # Called when object is nested under an object that receives + # #with_indifferent_access. This method with be called on the current object + # by the enclosing object and is aliased to #with_indifferent_access by + # default. Subclasses of Hash may overwrite this method to return +self+ if + # converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be + # desirable. + # + # b = {:b => 1} + # {:a => b}.with_indifferent_access["a"] # calls b.nested_under_indifferent_access + # + alias nested_under_indifferent_access with_indifferent_access end diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 79a0de7940..8ec4f6e09a 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -140,8 +140,8 @@ module ActiveSupport end def convert_value(value) - if value.class == Hash - self.class.new_from_hash_copying_default(value) + if value.is_a? Hash + value.nested_under_indifferent_access elsif value.is_a?(Array) value.dup.replace(value.map { |e| convert_value(e) }) else diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index fbc40d1b69..762a64a881 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -43,6 +43,10 @@ module ActiveSupport end end + def nested_under_indifferent_access + self + end + # Hash is ordered in Ruby 1.9! if RUBY_VERSION < '1.9' diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 3ef080e1cb..4557a10688 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -16,6 +16,12 @@ class HashExtTest < Test::Unit::TestCase class SubclassingHash < Hash end + class NonIndifferentHash < Hash + def nested_under_indifferent_access + self + end + end + def setup @strings = { 'a' => 1, 'b' => 2 } @symbols = { :a => 1, :b => 2 } @@ -109,9 +115,12 @@ class HashExtTest < Test::Unit::TestCase assert_equal @strings, @mixed.with_indifferent_access.dup.stringify_keys! end - def test_hash_subclass - flash = { "foo" => SubclassingHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access - assert_kind_of SubclassingHash, flash["foo"] + def test_nested_under_indifferent_access + foo = { "foo" => SubclassingHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access + assert_kind_of ActiveSupport::HashWithIndifferentAccess, foo["foo"] + + foo = { "foo" => NonIndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access + assert_kind_of NonIndifferentHash, foo["foo"] end def test_indifferent_assorted diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 50168fa78f..bf99a701a6 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -243,6 +243,11 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal @other_ordered_hash.keys, @ordered_hash.keys end + def test_nested_under_indifferent_access + flash = {:a => ActiveSupport::OrderedHash[:b, 1, :c, 2]}.with_indifferent_access + assert_kind_of ActiveSupport::OrderedHash, flash[:a] + end + def test_each_after_yaml_serialization values = [] @deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash)) |