読者です 読者をやめる 読者になる 読者になる

Ruby の &. と #try の違い

Ruby

Ruby 2.3 で Safe Navigation Operator(&.)という新しい演算子が追加されました。 これは obj&.to_i という風にメソッド呼び出しのように使い、レシーバが nil の場合に nil を返します。

10&.to_s  # => "10"
nil&.to_s # nil

このように nil チェックすることなく安全にメソッドを呼び出すことが出来ます。

#try

RailsActiveSupport にも #try という似たようなメソッドが定義されています。 これはレシーバがメソッドが呼びだせる場合にそのメソッドを呼び出すというような処理になります。 また、レシーバが nil の場合は必ず nil を返します。

10.try(:to_s)   # => "10"
nil.try(:to_s)  # => nil

&.#try の違い

両方とも『レシーバが nil ではない場合にメソッドを呼び出す』という目的なんですが、具体的な挙動は少し違っています。 &.が『nilでない場合にメソッドを呼び出す』のに対して、#try は『メソッドを呼び出すことができるときにメソッドを呼び出す』というような挙動になります。 どういうことかというと

# 10 には #hoge メソッドは定義されていない(呼び出せない)ので nil を返す
10.try(:hoge)   # => nil

# レシーバは nil ではないので #hoge メソッドを呼びだそうとするが
# #hoge メソッドは定義されてないのでエラー
10&.hoge # => Error: undefined method `hoge' for 10:Fixnum (NoMethodError)

というような挙動になります。
これは #tryrespond_to? を使用して『メソッドを呼びだせるかどうか』をチェックしているためです。
このような違いがあるため &.#try の代替として使用する場合は注意して使用する必要があります。

共通の挙動

#try&. もレシーバが nil の場合は nil しか返しません。

nil&.nil?      # => nil
nil.try(:nil?) # => nil