web-dev-qa-db-ja.com

Rubyの `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>

&..tryのショートカットだと思っていましたが、間違っていたと思います。誰かが私が行方不明になっていることに関して正しい方向を教えてくれますか?

私はそれがRuby関連ではないように感じます。グレープかもしれませんか?.

20
Adrien

&.は、#try!ではなく、#tryと同様に機能します。

そして、これは#try!の説明です( documentation から):

#tryと同じですが、受信がnilでなく、試行されたメソッドが実装されていない場合、NoMethodError例外が発生します。

したがって、基本的にnilでメソッドを呼び出す必要はありませんが、オブジェクトが提示されると、通常どおりそのメソッドを呼び出そうとします。

引用はRails Documentationからのものです。したがって、Rubyは#tryを提供しません; Railsによって提供されるか、より正確に提供することを強調することが重要です。 ActiveSupport。 安全なナビゲーション演算子&.)は、Ruby 2.3.0。

39
Danil Speransky

tryメソッドは多くのことを無視します。うまくいかない場合は、単に試してみて1日と呼びます。

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

12
tadman

私はここに少し遅れてパーティーに到着しています。他の答えはそれがどのように機能するかをカバーしていますが、私は他の答えがカバーしていない何かを追加したかったです。

Rubytry&.の違いは何ですか? Rubyここで重要な言葉である。

最大の違いは、tryがRubyに存在しないことです。これはRailsが提供するメソッドです。 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プロジェクトで使用できます。

4
John Hayes-Reed

コメントセクションの@Redithionに同意する

Rubyの安全なナビゲーションオペレーター(&。)

nilオブジェクトでメソッドが呼び出された場合、安全なナビゲーション演算子はnilを返します。これより前に、nilオブジェクトでメソッドが呼び出された場合、以下のエラーがスローされます。

$ nil.some_method
=> NoMethodError: undefined method 'some_method' for nil:NilClass

安全なナビゲーションが必要な理由

多くの場合、入力値が正しくないためオブジェクトを取得できません。この場合、オブジェクトがあると想定してメソッドの呼び出しを続行すると、オブジェクトがnilオブジェクトになるとコードが壊れる可能性があります。

そのような場合を避けるために、安全なナビゲーションが導入されています。これにより、メソッドが呼び出されるオブジェクトがnilオブジェクトであっても、コードが破損しないことが保証されます。これは、メソッド呼び出しが失敗したときにnilオブジェクトを受け取ることができる場合に使用する必要があります。

所有者のいるアカウントがあり、所有者の住所を取得したいとします。安全であり、Nilエラーのリスクを避けたい場合は、次のように記述します。

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

これは本当に冗長で入力するのが面倒です。 ActiveSupportには、同様の動作を持つtryメソッドが含まれています(ただし、後で説明する重要な違いはほとんどありません)。

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

同じことを実現します。チェーンに沿った値がnilの場合、アドレスまたはnilを返します。最初の例は、たとえば所有者がfalseに設定されている場合にもfalseを返す場合があります。

&を使用

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

account&.owner&.address
0
Mayur Shah