Ruby 2.5 introduced several new methods. Everyone is happy for yield_self (don’t get my wrong, me too), but I’m very excited for one I’ve been waiting for: Hash#transform_keys.

It does exactly what it name implies, it provides a way to transform each key on the Hash.

What’s the use for this? well, let’s explore one of them.

Say we’re writing a method that takes a Hash and returns a Json string representing that hash for an API. Lets take a look at an example input:

# >> {
# >>     #<Account   email = "peter@example.com",
# >>                 name = "Peter"> => [ "admin", "author" ]
# >>     ],
# >>     #<Account   email = "dave@example.com",
# >>                 name = "David"> => [ "editor", "author" ]
# >>     ],
# >>     #<Account   email = "matt@example.com",
# >>                 name = "Matt"> => [ "author" ]
# >> }

But that’s not good for our API. As keys, we only need the email to show.

In order to do this in a Ruby version prior to 2.5, we’d need to iterate over the hash assigning the old values to the new keys. But in Ruby 2.5, we can now do it like this:

Account = Struct.new(:name, :email)

accounts = {
  Account.new("Peter", "peter@example.com") => ["admin", "author"],
  Account.new("David", "dave@example.com")  => ["editor", "author"],
  Account.new("Matt",  "matt@example.com")  => ["author"],
}


accounts.transform_keys { |key| key.email }
# => {"peter@example.com"=>["admin", "author"],
#     "dave@example.com"=>["editor", "author"],
#     "matt@example.com"=>["author"]}

Hash#transform_keys receives a block and will transform each one of the keys with the value returned from the block.

Note that the conversion can be as complex as needed, but in this case, we could use Symbol#to_proc and make this code look much easier.

accounts.transform_keys(&:email)
# => {"peter@example.com"=>["admin", "author"],
#     "dave@example.com"=>["editor", "author"],
#     "matt@example.com"=>["author"]}

I really can’t wait to put this method into practice. Thanks for reading.

Saluti.