Rails try hash key access

Rails ActiveSupport provides try method on an object. Try is used to call a method on an object if it is not nil, otherwise return nil. Try method also be used on a hash key to access the value or return nil if the value is not available.

We will also see how we can use fetch to access hash keys.

Let’s take a hash for an example.

hash = {
  author: 'Akshay',
  type: 'Blog Post',
  published: true
}

Try Hash Key

We can use try to fetch value of a hash key as given below.

hash.try(:[], :author)
# => "Akshay"

As, we can see it returns proper value.

Now, if we use try to access non-existent key in the hash, it will return nil as given in the example below.

non_existent_key = :post_title
hash.try(:[], non_existent_key)
# => nil

Note:

  • try is like Object#send, but it returns nil if calling object is nil
  • The first argument :[], it’s a method call on object with argument as the hash key.

Thus, try is more helpful, if we want to call method on objects and we are not sure if the calling object is nil or a valid object.

Using fetch on hash

We can directly access value of hash key in ruby as given below.

hash[:author]
# => "Akshay"

It will return value of the key. If the key is not found, it will return nil.

As we can see, the above line using hash access gives us the same behavior that we had using try. That is, it returns nil if value for the key :author is not found. Otherwise, it returns the value found.

non_existent_key = :author_role
hash.fetch(non_existent_key, 'Admin')
# => "Admin"

fetch is particularly useful if

  • Raise an exception if value is not found
  • Specify a default value returned if value is not found for the key.

As given in the example above, it returns value Admin as specified in fetch

Why don’t we just use hash access or fetch method available on Hash from Ruby?

Well, it depends on the use case. Consider the same example given above.

  • If we are sure about the variable hash is actually a hash, then we can confidently use fetch instead of try
  • try returns nil even if caller is nil.
hash = nil
hash.fetch(:author, nil)
# > NoMethodError (undefined method `fetch' for nil:NilClass)

As you can see, this raises NoMethodError on nil.

We can still use plain ruby and guard against raising this exception using safe navigation operator in ruby

hash = nil
hash&.fetch(:author, nil)
# => nil

Conclusion

To conclude, we should know the minor caveats of each method to decide which should be used. Hope, you found this article helpful in some way.