diff options
author | Leo Cassarani <leo.cassarani@me.com> | 2012-09-03 23:13:49 +0100 |
---|---|---|
committer | Leo Cassarani <leo.cassarani@me.com> | 2012-09-05 00:59:29 +0100 |
commit | edab820d9ee5c18780e11752d46d7df73c820ddb (patch) | |
tree | fbe62a00a861fc9fcd1338b48df9df96da4e3c0e /activesupport/lib | |
parent | 7995c03dc0e8ff8448427de16c98f77aa8bb6a01 (diff) | |
download | rails-edab820d9ee5c18780e11752d46d7df73c820ddb.tar.gz rails-edab820d9ee5c18780e11752d46d7df73c820ddb.tar.bz2 rails-edab820d9ee5c18780e11752d46d7df73c820ddb.zip |
Extend HashWithIndifferentAccess#update to take an optional block
When a block is passed into the method, it will be invoked for each
duplicated key, with the key in question and the two values as
arguments. The value for the duplicated key in the receiver will
be set to the return value of the block.
This behaviour matches Ruby's long-standing implementation of
Hash#update and is intended to provide a more consistent interface.
HashWithIndifferentAccess#merge is also affected by the change, as it
uses #update internally.
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/active_support/hash_with_indifferent_access.rb | 27 |
1 files changed, 21 insertions, 6 deletions
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 |