rubyguides

Hash#update

update(*other_hashes) → self

Signature

update(*other_hashes) → self
update(*other_hashes) {|key, old_value, new_value| block } → self

update takes zero or more hash arguments and optionally a block. It always returns self — the same hash object that was modified in place.

Basic Usage

Give update one or more hashes and it merges them into the receiver, overwriting duplicate keys:

h = {a: 1, b: 2}
h.update({b: 3, c: 4})
h # => {:a=>1, :b=>3, :c=>4}

The original hash is modified. update returns the same object it just mutated.

Block Form

When a key appears in both hashes, you can pass a block to resolve the conflict:

h = {items: 5, threshold: 10}
h.update({items: 3, threshold: 12}) { |_key, old, new| old + new }
h # => {:items=>8, :threshold=>22}

The block receives key, old_value, and new_value and its return value becomes the final value for that key. In the example above, the new items value is 5 + 3 = 8, not just 3.

No Arguments

Calling update with no arguments simply returns self unchanged:

h = {x: 1, y: 2}
h.update      # => {:x=>1, :y=>2}
h.update { }  # => {:x=>1, :y=>2}  (block is ignored)

Note that this is not a copy — the method returns the same object. There is no update form that returns a modified copy like merge does.

Multiple Hashes

You can pass multiple hashes. They are merged left to right, so later hashes win on conflicts:

h = {a: 1}
h.update({a: 2}, {a: 3}, {a: 4})
h # => {:a=>4}

Each duplicate key is overwritten by whichever hash came later in the argument list.

Alias for Hash#merge!

update is exactly the same method as Hash#merge! — they share the same implementation. Use whichever name reads better in your context:

h = {x: 1}
h.merge!({y: 2})   # => {:x=>1, :y=>2}
h.update({z: 3})   # => {:x=>1, :y=>2, :z=>3}

Gotchas

Returns self, not a copy. Many Ruby hash methods return a new hash — merge returns a new hash, for example. update returns the mutated original, so be careful not to chain it expecting a copy back.

h = {a: 1}
result = h.update({b: 2})
result.equal?(h)   # => true  (same object)

TypeError on non-Hash arguments. Each argument must be a Hash. Passing a non-hash raises TypeError:

h = {}
h.update("foo")
# => TypeError: no implicit conversion of String into Hash

No automatic flattening. If you pass a hash containing array values, those arrays are not recursively merged:

h = {nested: {a: 1}}
h.update(nested: {b: 2})
h # => {:nested=>{:b=>2}}  # the original :a is gone, not deep-merged

Ruby does not provide a built-in deep merge. The outer key is simply overwritten.

See Also

  • Hash#merge — returns a new merged hash without modifying the original
  • Hash#merge! — the canonical name for this method
  • Hash#dig — safely retrieve nested hash values