diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2012-09-04 17:07:17 -0700 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2012-09-04 17:07:17 -0700 |
commit | ac5089d769d612a596c437085acd3c4ef257ab4e (patch) | |
tree | fbe62a00a861fc9fcd1338b48df9df96da4e3c0e /activesupport | |
parent | 7995c03dc0e8ff8448427de16c98f77aa8bb6a01 (diff) | |
parent | edab820d9ee5c18780e11752d46d7df73c820ddb (diff) | |
download | rails-ac5089d769d612a596c437085acd3c4ef257ab4e.tar.gz rails-ac5089d769d612a596c437085acd3c4ef257ab4e.tar.bz2 rails-ac5089d769d612a596c437085acd3c4ef257ab4e.zip |
Merge pull request #7519 from leocassarani/merge-with-block
Add an optional block to HashWithIndifferentAccess#update and #merge
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG.md | 6 | ||||
-rw-r--r-- | activesupport/lib/active_support/hash_with_indifferent_access.rb | 27 | ||||
-rw-r--r-- | activesupport/test/core_ext/hash_ext_test.rb | 23 |
3 files changed, 50 insertions, 6 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 8dd88f9f62..761780fb8b 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,11 @@ ## Rails 4.0.0 (unreleased) ## +* An optional block can be passed to `HashWithIndifferentAccess#update` and `#merge`. + The block will be invoked for each duplicated key, and used to resolve the conflict, + thus replicating the behaviour of the corresponding methods on the `Hash` class. + + *Leo Cassarani* + * Remove `j` alias for `ERB::Util#json_escape`. The `j` alias is already used for `ActionView::Helpers::JavaScriptHelper#escape_javascript` and both modules are included in the view context that would confuse the developers. diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 5fd20673d8..71713644a7 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -95,10 +95,10 @@ 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 hash passed as argument: # # hash_1 = ActiveSupport::HashWithIndifferentAccess.new - # hash_2[:key] = "value" + # hash_1[:key] = "value" # # hash_2 = ActiveSupport::HashWithIndifferentAccess.new # hash_2[:key] = "New Value!" @@ -110,12 +110,27 @@ module ActiveSupport # In either case the merge respects the semantics of indifferent access. # # If the argument is a regular hash with keys +:key+ and +"key"+ only one - # of the values end up in the receiver, but which was is unespecified. + # of the values end up in the receiver, but which one is unspecified. + # + # When given a block, the value for duplicated keys will be determined + # by the result of invoking the block with the duplicated key, the value + # in the receiver, and the value in +other_hash+. The rules for duplicated + # keys follow the semantics of indifferent access: + # + # 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) else - other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + other_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)) + end self end end @@ -173,8 +188,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) - self.dup.update(hash) + def merge(hash, &block) + self.dup.update(hash, &block) end # Like +merge+ but the other way around: Merges the receiver into the diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 4dc9f57038..37fdf1c0af 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -428,6 +428,29 @@ class HashExtTest < ActiveSupport::TestCase assert_equal 2, hash['b'] end + def test_indifferent_merging_with_block + hash = HashWithIndifferentAccess.new + hash[:a] = 1 + hash['b'] = 3 + + other = { 'a' => 4, :b => 2, 'c' => 10 } + + merged = hash.merge(other) { |key, old, new| old > new ? old : new } + + assert_equal HashWithIndifferentAccess, merged.class + assert_equal 4, merged[:a] + assert_equal 3, merged['b'] + assert_equal 10, merged[:c] + + other_indifferent = HashWithIndifferentAccess.new('a' => 9, :b => 2) + + merged = hash.merge(other_indifferent) { |key, old, new| old + new } + + assert_equal HashWithIndifferentAccess, merged.class + assert_equal 10, merged[:a] + assert_equal 5, merged[:b] + end + def test_indifferent_reverse_merging hash = HashWithIndifferentAccess.new('some' => 'value', 'other' => 'value') hash.reverse_merge!(:some => 'noclobber', :another => 'clobber') |