Ruby on Railsで使われるtryとtry!と&.(ぼっち演算子)の違い

Ruby on Railsの開発をしていると特殊な関数(tryとtry!と&.(ぼっち演算子))を見ますねよ。同じ処理ですが微妙に違います。

おすすめは「&.」を使用するのが最も良いと考えています。

  • tryはNoMethodErrorを握りつぶしてしまうので、極力使用しないのがベター
  • try!より&.の方が使える環境が多い(try!はRails、&.はRuby)
  • try!より&.の方が高速
  • try!より&.の方がコードの記述量が少なく可読性が高い

ではそれぞれのメソッド(演算子)とその理由について詳細を説明します。

try

tryはメソッドが定義されていない場合やオブジェクトがnilの場合に、その結果がnilとなるように返してくれます。オブジェクトがnilでなく、メソッドが定義されている場合はそのメソッドを呼び出します。

# Stringオブジェクトのto_iメソッドを呼び出している
irb(main):313:0> "hoge".try(:to_i)
=> 0

# Stringオブジェクトに定義されていないメソッドはnilになる
irb(main):314:0> "hoge".try(:to_fuga)
=> nil

# nilに対して行うとnilになる
irb(main):318:0> nil.try(:to_i)
=> nil


try!

try!は基本的にtryと同じですが、メソッドが存在しない場合にNoMethodErrorが発生します。

# tryと同じ挙動
irb(main):319:0> "hoge".try!(:to_i)
=> 0

# メソッドがない場合はNoMethodErrorが起きる
irb(main):322:0* "hoge".try!(:to_fuga)
NoMethodError: undefined method `to_fuga' for "hoge":String
Did you mean?  to_f
    from (irb):322

# tryと同じ挙動
irb(main):323:0> nil.try!(:to_i)
=> nil

&. (ぼっち演算子)

&.はぼっち演算子と呼ばれています。挙動はtry!と同じです。
Ruby2.3で追加されました。

# try!と同じ挙動
irb(main):001:0> "hoge"&.to_i
=> 0

# try!と同じ挙動
irb(main):002:0> "hoge"&.to_fuga
NoMethodError: undefined method `to_fuga' for "hoge":String
Did you mean?  to_f
    from (irb):2

# try!と同じ挙動
irb(main):003:0> nil&.to_i
=> nil

考察

tryは使わない方が良さそう

「tryを使えばNoMethodErrorが出ないし安全!」とも思えますが、オブジェクトやメソッドがない場合にエラーとせずすべてnilとしてしまうので、一見正しく動いたように見え、バグに気づかない恐れがあります。

また、NoMethodErrorについてはそもそも存在しないメソッドを呼び出している時点で期待していたオブジェクトと異なるクラスのオブジェクトが設定されてたり、メソッドが実装されていなかったりとよろしくない状態なので、実装を見直した方が良いです。

よって、基本的にtryは使わない方が良いと考えています。
もちろんこれらを理解したうえでtryが適していると判断したのであれば問題ありませんが、思考停止になってとりあえずtryをつけているパターンは危ないので見直した方が良いでしょう。

ボッチ演算子(&.)を使った方が良いです。