概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Safe navigation operator in Ruby
- 原文公開日: 2017/11/17
- 著者: Akshay Mohite
Rubyのぼっち演算子はRailsのObject#tryより高速(翻訳)
&.というsafe navigation演算子(Null条件演算子: Rubyでは「ぼっち演算子」とも呼ばれます)はRuby 2.3で導入されました。この演算子は、nilオブジェクトに対してメソッドが呼び出されたときにnilを返します。この演算子がなかったときは、nilオブジェクトに対して呼び出しを行うと以下のようにエラーになりました。
nil.some_method
#=> NoMethodError: undefined method 'some_method' for nil:NilClass
safe navigationが必要な理由
入力値が正しくない場合にオブジェクトを取得できないことは非常によくあります。このような場合、オブジェクトが取れることを期待してメソッド呼び出しを続行すると、オブジェクトがnilの場合に動かなくなるかもしれません。
safe navigationはこうした状況を避けるために導入されました。これを用いて、呼び出すオブジェクトがnilであってもコードが動き続けるようにできます。safe navigationは、メソッド呼び出しが失敗したときにnilオブジェクトを受け取ってもよい場合に使うべきです。
ActiveSupportのtry
RailsではActiveSupportの#tryメソッドが利用でき、上述のsafe navigationと似ています。メソッド名からわかるように、#tryはそのオブジェクトが利用可能な場合にメソッド呼び出しを試みます。nilオブジェクトに対してメソッド呼び出しが行われようとすると、エラーではなくnilを返します。
nil.try(:some_method)
#=> nil
Ruby 2.3のsafe navigation
オブジェクトがnilかどうかわからない場合は、たとえば以下のようにメソッド呼び出しの前にアンパサンド&を追加するだけで使えます。
nil&.some_method
#=> nil
上のコードは例外をスローせずにnilを返します。
このコードは次のコードと同等です。
nil ? nil.some_method : nil
つまりオブジェクトがtrueと評価されればオブジェクトに対してメソッドを呼び出し、falseと評価されればnilを返します。
#tryとsafe navigationのどっちを使うか
Railsで仕事をすることが多い人は#tryを常用していることでしょう。#tryとsafe navigation演算子&.のパフォーマンスを比較してみると、Rubyでサポートされているsafe navigation演算子の方が遥かに高速で、しかもActiveSupportなどRailsの機能に依存しません。