Skip to content

Commit

Permalink
Merge pull request #12550 from Peeja/hash-wia-update-respects-to-hash
Browse files Browse the repository at this point in the history
HashWithIndifferentAccess#update respects #to_hash
  • Loading branch information
rafaelfranca committed Mar 28, 2014
2 parents 555ec36 + 03f35a2 commit 74d7df1
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
7 changes: 7 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
* `HashWithIndifferentAccess` better respects `#to_hash` on objects it's
given. In particular, `.new`, `#update`, `#merge`, `#replace` all accept
objects which respond to `#to_hash`, even if those objects are not Hashes
directly.

*Peter Jaros*

* Deprecate `Class#superclass_delegating_accessor`, use `Class#class_attribute` instead.

*Akshay Vishnoi*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def nested_under_indifferent_access
end

def initialize(constructor = {})
if constructor.is_a?(Hash)
if constructor.respond_to?(:to_hash)
super()
update(constructor)
update(constructor.to_hash)
else
super(constructor)
end
Expand All @@ -72,6 +72,7 @@ def default(key = nil)
end

def self.new_from_hash_copying_default(hash)
hash = hash.to_hash
new(hash).tap do |new_hash|
new_hash.default = hash.default
end
Expand Down Expand Up @@ -125,7 +126,7 @@ def update(other_hash)
if other_hash.is_a? HashWithIndifferentAccess
super(other_hash)
else
other_hash.each_pair do |key, value|
other_hash.to_hash.each_pair do |key, value|
if block_given? && key?(key)
value = yield(convert_key(key), self[key], value)
end
Expand Down
40 changes: 40 additions & 0 deletions activesupport/test/core_ext/hash_ext_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ def nested_under_indifferent_access
end
end

class HashByConversion
def initialize(hash)
@hash = hash
end

def to_hash
@hash
end
end

def setup
@strings = { 'a' => 1, 'b' => 2 }
@nested_strings = { 'a' => { 'b' => { 'c' => 3 } } }
Expand Down Expand Up @@ -411,6 +421,12 @@ def test_indifferent_update
assert [updated_with_strings, updated_with_symbols, updated_with_mixed].all? { |h| h.keys.size == 2 }
end

def test_update_with_to_hash_conversion
hash = HashWithIndifferentAccess.new
hash.update HashByConversion.new({ :a => 1 })
assert_equal hash['a'], 1
end

def test_indifferent_merging
hash = HashWithIndifferentAccess.new
hash[:a] = 'failure'
Expand All @@ -430,6 +446,12 @@ def test_indifferent_merging
assert_equal 2, hash['b']
end

def test_merge_with_to_hash_conversion
hash = HashWithIndifferentAccess.new
merged = hash.merge HashByConversion.new({ :a => 1 })
assert_equal merged['a'], 1
end

def test_indifferent_replace
hash = HashWithIndifferentAccess.new
hash[:a] = 42
Expand All @@ -442,6 +464,18 @@ def test_indifferent_replace
assert_same hash, replaced
end

def test_replace_with_to_hash_conversion
hash = HashWithIndifferentAccess.new
hash[:a] = 42

replaced = hash.replace(HashByConversion.new(b: 12))

assert hash.key?('b')
assert !hash.key?(:a)
assert_equal 12, hash[:b]
assert_same hash, replaced
end

def test_indifferent_merging_with_block
hash = HashWithIndifferentAccess.new
hash[:a] = 1
Expand Down Expand Up @@ -893,6 +927,12 @@ def test_compact!
assert_equal({}, h.compact!)
assert_equal({}, h)
end

def test_new_with_to_hash_conversion
hash = HashWithIndifferentAccess.new(HashByConversion.new(a: 1))
assert hash.key?('a')
assert_equal 1, hash[:a]
end
end

class IWriteMyOwnXML
Expand Down

0 comments on commit 74d7df1

Please sign in to comment.