ruby-on-railsrubyexceptionrescue

effectively applying nil check in ruby


I have this code

args = x.lead_details.last.leads.last.country_id rescue nil
Function(args)

I have used rescue keyword to make sure I don't get errors like

 undefined method `country_id' for nil:NilClass,
 undefined method `leads' for nil:NilClass

Is there any better way I can achieve this?

Other approach is

Function(x.lead_details.last.leads.last.country_id if x.present? && x.lead_details.present? && x.lead_details.last? && so on)

Solution

  • rescue nil is evil. It does not just rescue nil errors. It eats everything you throw at it. For example:

    class Foo
      def bar
      end
    
      def woo
        raise ArgumentError
      end
    end
    
    Foo.new.baz rescue nil # nil!
    Foo.new.woo rescue nil # nil!
    

    This applies to any inline rescue.

    Ruby 2.3.0 introduced the safe navigation operator that lets you do:

    x&.lead_details&.last&.leads&.last&.country_id
    

    ActiveSupport also has a Object#try! method that can be used in older versions of Ruby:

    x.try!(:lead_details).try!(:last).try!(:leads).try!(:last).try!(:country_id)
    

    But you're really just pissing on the Law of Demeter here and you should refactor the code so you don't have to traverse down that insane method chain as you're really just burying tons of potential bugs and making debugging impossible.

    See: