Given a hash such as:
AppConfig = {
'service' => {
'key' => 'abcdefg',
'secret' => 'secret_abcdefg'
},
'other' => {
'service' => {
'key' => 'cred_abcdefg',
'secret' => 'cred_secret_abcdefg'
}
}
}
I need a function to return service/key in some cases and other/service/key in other cases. A straightforward way is to pass in the hash and an array of keys, like so:
def val_for(hash, array_of_key_names)
h = hash
array_of_key_names.each { |k| h = h[k] }
h
end
So that this call results in 'cred_secret_abcdefg':
val_for(AppConfig, %w[other service secret])
It seems like there should be a better way than what I've written in val_for().
Accessing a specific element in a nested hash is very similar to a nested array. It is as simple as calling hash[:x][:y] , where :x is the key of the hash and :y is the key of the nested hash.
Are nested hashes possible in Ruby? The hashes that you've seen so far have single key/value pairs. However, just like arrays, they can be nested, or multidimensional.
Nested hashes allow us to further group, or associate, the data we are working with. They help us to deal with situations in which a category or piece of data is associated not just to one discrete value, but to a collection of values.
Just like arrays, hashes can be created with hash literals. Hash literals use the curly braces instead of square brackets and the key value pairs are joined by =>. For example, a hash with a single key/value pair of Bob/84 would look like this: { "Bob" => 84 }.
def val_for(hash, keys)
keys.reduce(hash) { |h, key| h[key] }
end
This will raise an exception if some intermediate key is not found. Note also that this is completely equivalent to keys.reduce(hash, :[])
, but this may very well confuse some readers, I'd use the block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With