There are many approaches to this.
If you are using Ruby 2.3 or higher, you can use dig
my_hash.dig('key1', 'key2', 'key3')
Many people stick to a simple ruby ββand the && test chain.
You can use stdlib hash # fetch :
my_hash.fetch('key1', {}).fetch('key2', {}).fetch('key3', nil)
Some people like the binding of the ActiveSupport # try method.
my_hash.try(:[], 'key1').try(:[], 'key2').try(:[], 'key3')
Others use andand
myhash['key1'].andand['key2'].andand['key3']
Some people think that egocentric nils is a good idea (although someone might prey on you and torture you if they find you are doing it).
class NilClass def method_missing(*args); nil; end end my_hash['key1']['key2']['key3']
You can use Enumerable # reduce (or add an alias).
['key1','key2','key3'].reduce(my_hash) {|m,k| m && m[k] }
Or maybe expand the hash or just your target hash object using the nested search method
module NestedHashLookup def nest *keys keys.reduce(self) {|m,k| m && m[k] } end end my_hash.extend(NestedHashLookup) my_hash.nest 'key1', 'key2', 'key3'
Oh, and how could we forget maybe monad?
Maybe.new(my_hash)['key1']['key2']['key3']