-1

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)
code0079
  • 147
  • 3
  • 13
  • Just being curious: What does `Function` do (I don't find it in the [docs](https://ruby-doc.org/core-2.6.3/)), and according to what syntax rule can a `rescue` be passed as part of an expression? Could I then use an `ensure` as well at this place? – user1934428 Mar 20 '20 at 07:59
  • "Function" is the name of a random function. – code0079 Mar 20 '20 at 08:40
  • But how do you manage having a `rescue` in the parameter list? When I try this, I get a syntax error. – user1934428 Mar 20 '20 at 09:55
  • 1
    @user1934428 this is most likely psuedocode - you can't use rescue in a parameters list and "inline rescue" - eg `foo(bar) rescue SomeError` should not be used. https://thoughtbot.com/blog/don-t-inline-rescue-in-ruby – max Mar 20 '20 at 12:49
  • @max : Highly interesting .... pseudocode resulting in real Ruby error messages. code0079: If you want discuss a concrete problem, please also post your concrete code, instead of inventing your own syntax. – user1934428 Mar 20 '20 at 14:05
  • @user1934428 It was self explanatory. – code0079 Mar 20 '20 at 14:50
  • @max please remove the downvote. – code0079 Mar 23 '20 at 19:07
  • @code0079 I haven't downvoted the question. Maybe focus a bit more on the quality of your questions so they don't get downvoted? https://stackoverflow.com/help/how-to-ask – max Mar 23 '20 at 22:30

2 Answers2

4

You can use the safe navigation operator (&.) that was introduced in Ruby 2.3:

Function(x&.lead_details&.last&.leads&.last&.country_id)

It returns nil when you try to call a method on nil.

spickermann
  • 100,941
  • 9
  • 101
  • 131
4

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:

max
  • 96,212
  • 14
  • 104
  • 165