Dac Nguyen
Dac Nguyen

Reputation: 23

Which syntax will recomend between try and &. when we're dealing with nil value in Ruby on Rails?

Like the title, from 2.3.0 ruby version. We can use Safe Navigation Operator(&.) instead of try for dealing with nil value in Rails. But when I use the new syntax, my reviewer told that is not good for reviewer, or someone else about the meaning my code. So I would like to know which syntax I should use when work with nil value?

nil.try(:method)
nil&.method

Upvotes: 1

Views: 534

Answers (3)

Anuj Khandelwal
Anuj Khandelwal

Reputation: 1244

As mentioned in @dinjas's answer, .try is a method provided by Rails, whereas &. is a method that is provided by Ruby itself, and hence, will be usable outside Rails apps as well.

Additionally, the two operators do NOT work in EXACTLY the same manner. The safe navigation operator prevents NoMethodErrors only for those cases when it is invoked on a value which is nil. For example:

a = nil
a&.do_something # Result: nil
a = false
a&.do_something # Result: NoMethodError: undefined method `asd' for false:FalseClass

a.try(:do_something) # Result: nil

As seen above, while .try handles falsy values as well and returns nil as the response when a method is invoked on an object that does not support it. However, &. does not handle that and invokes methods on false as well. The same applies to blank strings.

In terms of what you should use, I believe that decision should be taken by having a discussion with your team. I believe neither of the methods are incorrect and either can be used. However, I would strongly recommend not using BOTH try and &. throughout the codebase as that could lead to unintended effects if the codebase grows large.

This blog by Georgi Mitrev describes the safe navigation operator in more depth and I would recommend giving it a read once.

Upvotes: 2

dinjas
dinjas

Reputation: 2125

try is a method provided by Rails' Active Support

The safe-navigation operator is provided by Ruby itself (since version 2.3).

If you were to open a Ruby console (not Rails), and define a method foo:

def foo
  :bar
end

You could see something like the following:

>> nil.try(:foo)
Traceback (most recent call last):
        4: from /Users/dinjas/.rbenv/versions/2.6.1/bin/irb:23:in `<main>'
        3: from /Users/dinjas/.rbenv/versions/2.6.1/bin/irb:23:in `load'
        2: from /Users/dinjas/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        1: from (irb):7
NoMethodError (undefined method `try' for nil:NilClass)
>> nil&.foo
=> nil

IMHO, I prefer using Ruby methods over Rails methods as they are usable outside of the context of Rails.

That said, I also feel that whichever you use, it should be used sparingly. In my experience, it's a symptom of writing timid code (see Avdi Grimm's book, Confident Ruby).

Upvotes: 1

Hisham Magdy
Hisham Magdy

Reputation: 144

  1. &. works like #try!, not #try. documentation
  2. #try not native in ruby but it is provided by rails.
  3. Safe navigation #&. is almost 3~4 times faster than using the #try
require 'active_support/all'
require 'benchmark'

foo = nil

puts Benchmark.measure { 10_000_000.times { foo.try(:boo) } }
puts Benchmark.measure { 10_000_000.times { foo&.boo } }

Output

      1.210000   0.000000   1.210000 (  1.211835)
      0.360000   0.000000   0.360000 (  0.363127)

Upvotes: 3

Related Questions