Chris Holtz LABS

Blog

Simplify your ruby hash injects with hmap

Have you ever had the pleasure of playing family tech support? I do! That's why I'm spending memorial day afternoon running windows updates. Woo! What to do while waiting... browse the Internet, check; clean likely malware candidates off their PCs, check; Zone out while listening to the wind, check. Oh! I can write a blog post about ruby inject!

Actually, I want to talk specifically about using the Hash class with inject. If you have a hash with a bunch of keys that are strings that you would like to convert to symbols, you'd do something like this:

>> x = { "first_name" => "John", "last_name" => "Smith" }
=> {"last_name"=>"Smith", "first_name"=>"John"}
>> x.inject({}){ |hash,(k,v)| hash.merge( k.to_sym => v) }
=> {:last_name=>"Smith", :first_name=>"John"}

This look somewhat familar? Cool, read on. If not, take a look here and then come back. Ok, another examples... maybe you want to flatten out some role permissions data:

>> x = { "user1" => [ "content_admin", "member" ], "user2" => [ "member_admin", "member" ]}
=> {"user1"=>["content_admin", "member"], "user2"=>["member_admin", "member"]}
>> x.inject({}){ |hash,(k,v)| hash.merge( k => v.join(",") ) }
=> {"user1"=>"content_admin,member", "user2"=>"member_admin,member"}

I'm quite fond of compact code provided it is somewhat readable and in this spirit, I really really don't like including hash.merge() in a block every time I use a hash inject in this way. To work around this, I built the function hmap(). Take a look:

All this does is wrap an inject statement and include a Hash.merge call. That way, The examples calls above would look like this:

>> x.hmap({}){ |k,v| { k.to_sym => v } }
>> x.hmap({}){ |k,v| { k => v.join(",") } }

I find this syntax much cleaner; the syntax doesn't get in the way of the solution so much.

Here are the associated unit tests:
Leave a Comment
Name *
required
Email *
required
Website
required
required