Ruby 2.5 added the methods Hash#transform_keys and Hash#transform_keys! to transform keys of a hash.
Before Ruby 2.8
These methods require a block that is used to transform all the keys of the hash.
Example
2.6.5 :001 > hash = {name: "John", zip: 12345, verified: true}
=> {:name=>"John", :zip=>12345, :verified=>true}
# Returns the hash with transformed keys as per the given block
2.6.5 :002 > hash.transform_keys(&:upcase)
=> {:NAME=>"John", :ZIP=>12345, :VERIFIED=>true}
# The bang sibling of this method mutates the hash in place
2.6.5 :003 > hash.transform_keys!(&:upcase)
=> {:NAME=>"John", :ZIP=>12345, :VERIFIED=>true}
2.6.5 :004 >
In the example above, all the keys of the hash were transformed to uppercase.
After Ruby 2.8 (to be 3.0.0)
Hash#transform_keys
and Hash#transform_keys!
will
now accept
an optional hash argument.
The keys of this hash argument represent the existing keys in the hash, and the values represent the new keys.
This allows us to selectively change the keys of a hash like below.
Example
irb(main):001:0> hash = {name: "John", zip: 12345, verified: true}
irb(main):002:0> hash.transform_keys({name: :first_name, zip: :zipcode})
=> {:first_name=>"John", :zipcode=>12345, :verified=>true}
irb(main):003:0>
In the example above, the keys name
and zip
were transformed to first_name
and zipcode
.
But the verified
key remained the same as it wasn’t there in the hash argument.
Passing both an argument and a block together
The hash takes priority over the block when both are passed to the method. Hence, the block is applied only to the keys which were not specified in the hash argument.
Example
hash = {name: "John", zip: 12345, verified: true}
irb(main):002:0> hash.transform_keys({name: :first_name, zip: :zipcode}, &:upcase)
# Only :verified was changed to uppercase as it wasn't specified in the hash argument
=> {:first_name=>"John", :zipcode=>12345, :VERIFIED=>true}
In the example above, the keys name
and zip
were transformed to first_name
and zipcode
as specified by the hash argument.
Also, the block passed was applied to the only residual key verified
and got transformed to uppercase.