How do I fetch multiple hash values at once?
What is a shorter version of this?:
from = hash.fetch(:from)
to = hash.fetch(:to)
name = hash.fetch(:name)
# etc
Note the fetch
, I want to raise an error if the key doesn't exist.
There must be shorter version of it, like:
from, to, name = hash.fetch(:from, :to, :name) # <-- imaginary won't work
It is OK to use ActiveSupport if required.
Use Hash's values_at
method:
from, to, name = hash.values_at(:from, :to, :name)
This will return nil
for any keys that don't exist in the hash.
Ruby 2.3 finally introduces the fetch_values
method for hashes that straightforwardly achieves this:
{a: 1, b: 2}.fetch_values(:a, :b)
# => [1, 2]
{a: 1, b: 2}.fetch_values(:a, :c)
# => KeyError: key not found: :c
hash = {from: :foo, to: :bar, name: :buz}
[:from, :to, :name].map{|sym| hash.fetch(sym)}
# => [:foo, :bar, :buz]
[:frog, :to, :name].map{|sym| hash.fetch(sym)}
# => KeyError
my_array = {from: 'Jamaica', to: 'St. Martin'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array
This will raise an error like you requested
my_array = {from: 'Jamaica', to: 'St. Martin', name: 'George'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array
This will return the array.
But OP asked for failing on a missing key...
class MissingKeyError < StandardError
end
my_hash = {from: 'Jamaica', to: 'St. Martin', name: 'George'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError
my_hash = {from: 'Jamaica', to: 'St. Martin'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError