Can you #dig it?

Chris Buggelli
Aug 27, 2017 · 2 min read

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]
#=> earth
planet[:continents]
#=> 7
planet[: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!

We can dig it.

)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade