---
title: Access Ruby Hash Values with Fallbacks for Missing Data
teaser: 'Find out different ways to access hash values in Ruby and save the dinosaurs
  at the same time.

  '
tags: code,rails,ruby,web
author: Rob Whittaker
published_on: 2017-09-25
---

Some of you may not been aware but there is more than one way to get a value out
of a hash. By the end of this article I will have told you about three of them
and the relative merits of each method.

The first is the one most Ruby developers know and love,
[`#[]`](http://ruby-doc.org/core-2.4.1/Hash.html#method-i-5B-5D). This is the
method we see when we first learn about hashes. It is how programmers from other
languages might access elements in arrays or hashes and we use it as follows.

```ruby
pets = { cat: "Jess" }
pets[:cat]
# => "Jess"
```

This is great. It does exactly what we want it to do. What if we have a
situation where the value might not exist? What happens then? Lets have a look.

```ruby
pets = { cat: "Jess" }
pets[:dinosaur]
# => nil
```

It's all right, you think. I'll deal with the `nil`.

```ruby
pets = { cat: "Jess" }
pets[:dinosaur] || "They all died :("
# => "They all died :("
```

What if, for some _crazy_ reason, your key is not `nil`, but `false`? You could
then end up fallbacking to a value you never intended to.

```ruby
dinosaurs = { alive?: false }
dinosaurs[:alive?] || true
# => true
```

What if the key does not exist in the hash at all? You would never know this,
unless you put some guard clause or error handling in place.

There is an answer to both of these scenarios and its name is [`#fetch`].

[`#fetch`]: http://ruby-doc.org/core-2.4.1/Hash.html#method-i-fetch

`#fetch` works in much the same way as `#[]`, but it also allows you to set a
fallback value for when the key does not exist or it is `nil`.

```ruby
pets = { cat: "Jess" }
pets.fetch(:dinosaur, "They all died :(")
# => "They all died :("
```

You may been wondering how this is any better than our example from earlier.
Let's look at another example.

```ruby
dinosaurs = { alive?: false }
dinosaurs.fetch(:alive?, true)
# => false
```

This seems to give a much better answer than our original solution. `#fetch`
only falls back to the default if the key does not exist or if the key's value
is `nil`. Here the `:alive?` is `false`. This is the returned value.

Now, what if we wanted to do something crazy like this.

```ruby
pets.fetch(:dinosaur, Dinosaur.raise_from_the_dead!)
```

When we use `#fetch` with two arguments, the second argument is always evaluated
even if it is never used. This could be an expensive operation. Think of all the
time and effort this would take. You would have to spend time finding some amber
with a mosquito in it. Then there is all the research and development behind the
science. In the end we all know life finds a way.

What we actually want is a way to only use the fallback if we need it. Luckily
such an operation exists.

```ruby
pets.fetch(:dinosaur) { Dinosaur.raise_from_the_dead! }
```

Now we will only be raising dinosaurs from the dead when we do not already have
a pet dinosaur. This seems sensible. Who has space for two dinosaurs? This is
particularly helpful when trying to introduce dependency injection.

You should now understand three ways to read a value from a hash, their relative
merits, and when to use them. Good luck!
