Merge pull request #36880 from freeletics/multiple-merge

Support multiple arguments in `HashWithIndifferentAccess` for `merge` and update methods
This commit is contained in:
Rafael Mendonça França 2019-08-08 18:27:44 -04:00
commit 6ebdab3239
No known key found for this signature in database
GPG Key ID: FC23B6D0F1EEE948
3 changed files with 47 additions and 13 deletions

View File

@ -1,3 +1,8 @@
* Support multiple arguments in `HashWithIndifferentAccess` for `merge` and `update` methods, to
follow Ruby 2.6 addition.
*Wojciech Wnętrzak*
* Allow initializing `thread_mattr_*` attributes via `:default` option
class Scraper

View File

@ -96,7 +96,7 @@ module ActiveSupport
alias_method :store, :[]=
# Updates the receiver in-place, merging in the hash passed as argument:
# Updates the receiver in-place, merging in the hashes passed as arguments:
#
# hash_1 = ActiveSupport::HashWithIndifferentAccess.new
# hash_1[:key] = 'value'
@ -106,7 +106,10 @@ module ActiveSupport
#
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
#
# The argument can be either an
# hash = ActiveSupport::HashWithIndifferentAccess.new
# hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
#
# The arguments can be either an
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
# In either case the merge respects the semantics of indifferent access.
#
@ -121,18 +124,15 @@ module ActiveSupport
# hash_1[:key] = 10
# hash_2['key'] = 12
# hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
def update(other_hash)
if other_hash.is_a? HashWithIndifferentAccess
super(other_hash)
def update(*other_hashes, &block)
if other_hashes.one?
update_with_single_argument(other_hashes.first, block)
else
other_hash.to_hash.each_pair do |key, value|
if block_given? && key?(key)
value = yield(convert_key(key), self[key], value)
end
regular_writer(convert_key(key), convert_value(value))
other_hashes.each do |other_hash|
update_with_single_argument(other_hash, block)
end
self
end
self
end
alias_method :merge!, :update
@ -259,8 +259,8 @@ module ActiveSupport
# This method has the same semantics of +update+, except it does not
# modify the receiver but rather returns a new hash with indifferent
# access with the result of the merge.
def merge(hash, &block)
dup.update(hash, &block)
def merge(*hashes, &block)
dup.update(*hashes, &block)
end
# Like +merge+ but the other way around: Merges the receiver into the
@ -393,6 +393,19 @@ module ActiveSupport
target.default = default
end
end
def update_with_single_argument(other_hash, block)
if other_hash.is_a? HashWithIndifferentAccess
regular_update(other_hash, &block)
else
other_hash.to_hash.each_pair do |key, value|
if block && key?(key)
value = block.call(convert_key(key), self[key], value)
end
regular_writer(convert_key(key), convert_value(value))
end
end
end
end
end

View File

@ -249,6 +249,14 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase
assert [updated_with_strings, updated_with_symbols, updated_with_mixed].all? { |h| h.keys.size == 2 }
end
def test_update_with_multiple_arguments
hash = HashWithIndifferentAccess.new
hash.update({ "a" => 1 }, { "b" => 2 })
assert_equal 1, hash["a"]
assert_equal 2, hash["b"]
end
def test_update_with_to_hash_conversion
hash = HashWithIndifferentAccess.new
hash.update HashByConversion.new(a: 1)
@ -274,6 +282,14 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase
assert_equal 2, hash["b"]
end
def test_merging_with_multiple_arguments
hash = HashWithIndifferentAccess.new
merged = hash.merge({ "a" => 1 }, { "b" => 2 })
assert_equal 1, merged["a"]
assert_equal 2, merged["b"]
end
def test_merge_with_to_hash_conversion
hash = HashWithIndifferentAccess.new
merged = hash.merge HashByConversion.new(a: 1)