Over a million developers have joined DZone.

Don’t Be Liberal When Being Aggressive: Ruby Hash’s Fetch With Defaults

Hash is an extremely flexible structure and we can't imagine our code without it. However, this flexibility comes with a hidden cost—uncertainty.

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

Hash is an extremely flexible structure and we can't imagine our code without it. However, this flexibility comes with a hidden cost—uncertainty. Consider this code:

def find_exchange_rate(data)
  amount = data[:amount]
  from_currency = data[:from_currency]
  to_currency = data[:to_currency]

  ... #persistence access code

In order to prevent situations where  data  attributes aren't defined, fetch comes to help.

def show_exchange_rate(data)
  amount = data.fetch(:amount)
  from_currency = data.fetch(:from_currency)
  to_currency = data.fetch(:to_currency)

If from_currency or to_currency isn't defined, the application fails. Now, the code is much more secure.

Here's the moment when you have to decide what the policy will be. One option is to go with exception raised when a key is not present, but another approach is to use a default value.

from_currency = data.fetch(:from_currency) { DEFAULT_CURRENCY }

At first glance, it's a very convenient way to make the application work. However, it's not. It's rather a first step to making your application a source of falsehood. It's just like I said in the title—we're both aggressive and liberal because we enforce you to pass the param, but in case you forget we don't tell you about it.

It's enough if your client makes a misspelling in his client code, for example this:

data = {
  value: 1000,
  from_curency: 'EUR', #missing r!
  to_currency: 'THB'


He'll get the rate of exchange. Moreover, it may seem that this rate is a valid value (USD is a bit cheaper than EUR but not enough to be easily noticeable). I don't have to tell what effects this may have!

In this situation, a lot of developers would say: If you had unit tests in your client code you wouldn't have a problem. Maybe we wouldn't have problems, but the world is not perfect, and if you can minimize effects of such errors, you should. Eventually, the API owner is responsible for data correctness, not the client. Usually, it's better to not deliver data at all than to deliver improper data.

More Secure But Still Vulnerable

The approach with fetch  is more secure but this code is not fully secured yet. When I forget to assign a correct value to any of  data  attributes, but all keys are present  nilw will be introduced.

data = {
  value: 1000,
  from_currency: 'EUR',
  to_currency: nil


Obviously, in order to guarantee everything is okay, we would have to introduce a dedicated validator.

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

ruby,hash,secure code

Published at DZone with permission of Damian Jaszczurowski. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}