Can you #dig it?
Yes you can. Hashes are important objects in programming that contain a list of key-value pairs. They are a common way to store corresponding data, making it easy to access something based on a key word. The format of a hash kind of resembles a dictionary, where you look up a word to find a definition. Check out this hash:
planet = { name: earth, continents: 7, oceans: 4 }The typical way to access a value is to call the key on the variable name, in brackets:
planet[:name]
#=> earthplanet[:continents]
#=> 7planet[:oceans]
#=> 4
Easy enough. But when you have a key-value pair that has a value of another key-value pair that has a value of another key-value pair, it can be a headache. It’s tough to see what each pair contains. What if a key contains an empty value? Using bracket notation, this would throw a NoMethod error and you’ll have to track down the empty value. It would be swell if there was some way to dig around this…

In Ruby, this does exist. It’s a magical incantation knows as the #dig method. Hashes aren’t always pretty, and it just makes sense that Ruby has a built in method to account for the pitfalls of messy hashes.
Observe the following nested hash:
me = { name: { first: { short: "Chris", full: "Christopher" }, last: { short: nil, full: "Buggelli" } }, stuff: ["game boy", { cds: ["Life Is Peachy", "White Pony", "Significant Other"] }, "snes"] }Accessing one value within the hash with bracket notation is not too messy:
me[:name][:first][:short]
#=> “Chris”The #dig method is very similar. If you know the keys for the value you want to return, just throw it into #dig like so:
me.dig(:name, :first, :short)
#=> "Chris"Now let’s go deeper to see where #dig really shines.
me[:stuff][1][:cds][2]
#=> "Significant Other"me.dig(:stuff, 1, :cds, 2)
#=> "Significant Other"
Looks a lot nicer than bracket notation! Here’s the real difference with #dig, though: if you try to access a key that doesn’t exist with bracket notation, it will throw a NoMethodError. But with #dig, it will simply return nil. This makes dig superior for traversing JSON from an API you may be unfamiliar with, where each object could look very different.
me[:stuff][1][:games][:cds]#=> NoMethodError: undefined method `[]' for nil:NilClassme.dig(:stuff, 1, :games, :cds)#=> nil
With #dig, you can avoid crashing your program on a hash with a missing value!

