2017-08-22 7 views
5

で `try`と`&.`(安全運航事業者)との違いは何ですか。ここに私のコードです:私は&..tryのショートカットですが、私は私が間違っていたと推測思っルビー

class Order < Grape::Entity 
    expose :id { |order, options| order.id.obfuscate } 
    expose :time_left_to_review do |order, options| 
    byebug 
    order&.time_left_to_review # ERROR 
    end 
    expose :created_at { |order, options| order.last_transition.created_at } 
end 

# NoMethodError Exception: undefined method `time_left_to_review' for #<Order:0x007f83b9efc970> 

。私が逃していることについて、誰かが私に正しい方向を指摘してくれるかもしれませんか?

私はそれがルビー関連でないように感じます。ブドウかもしれない?私はそれがどうなるかは分かりませんが。

+0

彼らはあなたが違い[ここ](詳細を読むことができ、同じではありませんhttp://mitrev.net/ruby/2015/11/13次の例を考えてみましょう/ the-in-ruby /) – Redithion

答えて

9

&.は、#tryではなく、#try!のように動作します。

そして、ここで(documentationから)#try!の説明である:

#tryと同じですが、受信がnilでないとしようとしたメソッドを実装していない場合NoMethodErrorの例外が発生します。

したがって、基本的にnilのメソッドを呼び出すことができなくなりますが、オブジェクトが提示されると、通常通りメソッドを呼び出そうとします。

引用文はRails Documentationのものですから、 にRubyは#try、それ以上はRails、より正確にはActiveSupportを提供していないことを強調することが重要です。安全なナビゲーションオペレータ&.は、Ruby 2.3.0で発表された言語機能です。

6

tryメソッドは多くのことを無視しています。状況がうまくいかない場合は、そのショットに1日を呼び出します。

&条件付きナビゲーションオプションブロックコールnilオブジェクトを呼び出します。他のものは有効であるとみなされ、完全な結果、例外が含まれます。

3

私はここに少し遅れて到着していますが、他の回答はどのように働いているのですか?私は他の答えがカバーしていないものを追加したかったのです。

ご質問についてtry&.の違いはですRubyです。ここではRubyがキーワードです。

最も大きな違いは、Rubyにはtryが存在しないことです。これはRailsによって提供されるメソッドです。あなたは、レールコンソールでこのような何かを行う場合は、このや自分自身を見ることができます:

[1, 2, 3].try(:join, '-') 
#=> "1-2-3" 

しかしあなたはIRBコンソールで同じことを行うならば、あなたが得る:

[1, 2, 3].try(:join, '-') 
NoMethodError: undefined method `try' for [1, 2, 3]:Array 

&.ですRuby標準ライブラリの一部であるため、RailsだけでなくRubyプロジェクトでも利用できます。

1

航行安全演算子(&コメント

@Redithionに同意します。)ルビー

シナリオ

にあなたがownerがあり、所有者のaddressを取得したいaccountを持っている想像してみてください。あなたは無記号エラーのリスク、安全でないようにしたい場合は、次のようなものを記述します。

if account && account.owner && account.owner.address 
... 
end 

これは、入力して本当に冗長と迷惑です。 - チェーンに沿っていくつかの値であれば、それのいずれかがアドレスまたはnilを返し

if account.try(:owner).try(:address) 
... 
end 

それは同じことを実現:activesupportのは、(後述するいくつかの重要な違いではなく)と同様の動作を持つtry方法を含み、 nil。最初の例では、たとえばownerがfalseに設定されている場合にfalseを返すこともあります。

&を使用します。

は、我々は安全なナビゲーション演算子を使用して、前の例を書き換えることができます。

account&.owner&.address 

より多くの例

のは、より詳細にすべての3つのアプローチを比較してみましょう。

account = Account.new(owner: nil) # account without an owner 

account.owner.address 
# => NoMethodError: undefined method `address' for nil:NilClass 

account && account.owner && account.owner.address 
# => nil 

account.try(:owner).try(:address) 
# => nil 

account&.owner&.address 
# => nil 

これまでのところ驚きはありません。 ownerfalseの場合はどうなりますか(面白いコードのエキサイティングな世界ではそうはないが不可能ではない)?

account = Account.new(owner: false) 

account.owner.address 
# => NoMethodError: undefined method `address' for false:FalseClass ` 

account && account.owner && account.owner.address 
# => false 

account.try(:owner).try(:address) 
# => nil 

account&.owner&.address 
# => undefined method `address' for false:FalseClass` 

は、ここで最初の驚きが来る - &.構文は唯一nilをスキップしますが、誤認識して! s1 && s1.s2 && s1.s2.s3構文とまったく同じではありません。

オーナーが存在しても、addressに反応しない場合はどうなりますか?例えば以下

account = Account.new(owner: Object.new) 

account.owner.address 
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8> 

account && account.owner && account.owner.address 
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>` 

account.try(:owner).try(:address) 
# => nil 

account&.owner&.address 
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>` 

混乱とnil&.nil?trueを返すべきです。

&.演算子を使用して、nil値をチェックするときは注意してください。

nil.nil? 
# => true 

nil?.nil? 
# => false 

nil&.nil? 
# => nil 

参考:here