I ran into a situation today where I needed to pull out all key/value pairs from a hash that matched the keys in a pre-existing array. This is what I initially came up with:
hash = { :foo => "foo", :bar => "bar", :bat => "bat" } hash.symbolize_keys.reject { |k, v| ![:foo, :bar].include?(k) } >>> returns { :foo => "foo", :bar => "bar" }
Kind of ugly, ain’t it? I sure don’t want to repeat those lines elsewhere. Let’s see if we can do better:
class Hash def select_all(*attrs) symbolize_keys.reject { |k, v| !attrs.include?(k) } end end { :foo => "foo", :bar => "bar", :bat => "bat" }.select_all(:foo, :bar) >>> returns { :foo => "foo", :bar => "bar" }
Now that’s more like it. Extending Hash
lets me call a method directly on my hash. I can also use this method anywhere in my Rails application if I place the Hash
code in lib/hash.rb
and require 'hash'
from my environment.rb
file. Isn’t Ruby beautiful?
Anyone else have a better way of doing this? I’m open to suggestions.
I would call it #select_keys, and I would glob lib/ in environment.rb.
Pit e-mailed me directly with this alternate solution:
Not bad. He says that depending on the size of the hash and the number of attributes, this
implementation could be faster.
Mike sends in another example for us, one that doesn’t copy the entire hash using
symbolize_keys
first: