Rescue nil in Ruby on Rails

Ruby on Rails developers use rescue nil to get default value if particular expression evaluation fails. rescue nil is bad, very bad in terms of performance. We will learn why it’s bad and what should be used in order to achieve the same result

Ruby rescue syntax:

5 / 0 rescue nil;

Above expression returns nil string, as 5/0 would raise ZeroDivisionError: divided by 0 exception causing flow to go in rescue block which is returning ‘Invalid’ string here.

Rescue usage:

You can rescue from particular expression and set a value to be returned if evaluation of the expression throws any exception.

Why rescue nil is bad?

  • When you use expression rescue nil , it will rescue from any kind of exception.
  • Even if you have syntax error or any kind of error in the block from which it’s rescued.
  • As we are not specifying the class from which we need to rescue exception.

Parent class Exception is used to rescue from the exception.

Ruby Exception Hierarchy

Given below is the exception hierarchy in ruby that will help you understand how exceptions are rescued -

More on Exception class on APIDock

rescue nil in ruby?

If you want to just get default value use ‘try’

e.g. suppose if you are unsure if the hash has key that you’re going to access and you do something like -

hash = {
  domain: {
    url: 'https://rubyinrails.com',
    title: 'Ruby in Rails'
  }
}

And you want to access category of domain and if you don’t find category you want to set it to ‘Other’

category = hash[:domain][:category].downcase rescue 'other'

When above code gets executed this will result in exception as hash[:domain][:category] will give nil and trying down method on nil would cause an exception.

But rescue handling in the expression will return ‘Other’

Use Try

For the same example explained above you can use try to avoid raising exception and then returning some default value.

category = hash.try(:[], :domain).try(:[], :category).try(:downcase)
  • First try(:[], :domain) will try looking hash[:domain] and will return nil if value not found or if tried on nil value
  • Second try(:[], :category) will try looking hash[:category] and will return nil if value not found or if tried on nil value
  • Last try(:downcase) will try calling downcase method on the object and returns nil if the calling object is nil otherwise result

Why to use try instead of rescue -

Below given benchmarking will show that why one should use try instead of rescue just to get the default value.

The above output clearly indicates that using rescue nil if hash access operation fails takes a lot of time than trying to get a value if exist.

The try method returns nil value if not present.

Operation rescue Default Value

If you want to get some default value if operation fails then instead of using rescue use try || Default Value

E.g.

data[:site].try(:[],:description).try(:[], :random_key) || 'Default Value'

If you have any concern or suggestion over approaches suggested in the post, please feel free to comment down below.

-->