web-dev-qa-db-de.com

Was ist der Unterschied zwischen "try" und "&." (Sicherer Navigationsoperator) in Ruby

Hier ist mein Code:

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>

Ich dachte &. ist eine Abkürzung für .try, aber ich schätze, ich habe mich geirrt. Kann mich jemand auf die richtige Richtung weisen, was mir fehlt?

Ich habe das Gefühl, dass es nicht mit Ruby zusammenhängt. Traube vielleicht? Obwohl ich nicht verstehe, wie es sein könnte.

15
Adrien

&. funktioniert wie #try!, nicht #try.

Und hier ist die Beschreibung von #try! (aus Dokumentation ):

Entspricht #try, löst jedoch eine NoMethodError-Exception aus, wenn der Empfang nicht null ist und die ausgeführte Methode nicht implementiert ist.

Im Grunde erspart es Ihnen, eine Methode für nil aufzurufen, aber wenn ein Objekt präsentiert wird, versucht es, seine Methode wie gewohnt aufzurufen.

Das Zitat stammt aus der Rails-Dokumentation. Daher ist es wichtig zu betonen, dass Ruby #try nicht bereitstellt. Es wird von Rails oder genauer von ActiveSupport bereitgestellt. Der sichere Navigationsoperator (&.) ist jedoch eine Sprachfunktion in Ruby 2.3.0.

32
Danil Speransky

Die try-Methode ignoriert viele Dinge. Sie gibt nur einen Versuch und einen Tag, wenn die Dinge nicht klappen.

Die &-bedingte Navigationsoption wird only Aufrufe von nil-Objekten blockieren. Alles andere gilt als gültig und wird mit vollen Konsequenzen fortgeführt, einschließlich Ausnahmen.

10
tadman

Ich komme etwas spät zu der Party an, die anderen Antworten haben gezeigt, wie es funktioniert, aber ich wollte etwas hinzufügen, das die anderen Antworten nicht behandelt haben.

Ihre Frage stellt sich: Was ist der Unterschied zwischen try und &. in Ruby . Ruby ist hier das Schlüsselwort.

Der größte Unterschied besteht darin, dass try in Ruby nicht vorhanden ist. Dies ist eine von Rails bereitgestellte Methode. Sie können dies oder sich selbst sehen, wenn Sie in der Rails-Konsole so etwas tun: 

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

Wenn Sie jedoch dasselbe in der irb-Konsole tun, erhalten Sie Folgendes: 

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

Der &. ist Teil der Ruby-Standardbibliothek und daher nicht in Rails, sondern in jedem Ruby-Projekt verfügbar.

3
John Hayes-Reed

stimme mit @Redithion im Kommentarbereich überein

Der sichere Navigationsoperator (&.) In Ruby

Sicherer Navigationsoperator gibt null zurück, wenn eine Methode für ein Nullobjekt aufgerufen wird. Wenn zuvor eine Methode für ein Null-Objekt aufgerufen wird, wird ein Fehler ausgegeben, wie unten angegeben.

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

Warum brauchen wir eine sichere Navigation?

Oft erhalten wir aufgrund falscher Eingabewerte keine Objekte. Wenn wir in diesem Fall mit dem Aufruf von Methoden fortfahren, die erwarten, dass wir über ein Objekt verfügen, kann der Code beschädigt werden, wenn das Objekt als Nullobjekt angezeigt wird.

Um einen solchen Fall zu vermeiden, wird eine sichere Navigation eingeführt. Dadurch wird sichergestellt, dass unser Code auch dann nicht beschädigt wird, wenn das Objekt, für das die Methode aufgerufen wird, kein Objekt ist. Dies sollte verwendet werden, wenn wir mit dem Empfang von nil object zufrieden sind, wenn der Methodenaufruf fehlschlägt.

Beispiele

Stellen Sie sich vor, Sie haben ein Konto mit einem Eigentümer und möchten die Adresse des Besitzers erhalten. Wenn Sie sicher sein wollen und keinen Nil-Fehler riskieren möchten, schreiben Sie etwas wie das Folgende.

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

Das ist wirklich wortreich und nervig beim Tippen. ActiveSupport enthält die try-Methode, die ein ähnliches Verhalten aufweist (jedoch mit einigen wichtigen Unterschieden, die später erläutert werden):

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

Es bewirkt dasselbe - es gibt entweder die Adresse zurück oder null, wenn ein Wert entlang der Kette gleich Null ist. Das erste Beispiel kann auch false zurückgeben, wenn der Besitzer beispielsweise auf false gesetzt ist.

Verwenden von &.

Wir können das vorherige Beispiel mit dem sicheren Navigationsoperator umschreiben:

account&.owner&.address
1
Mayur Shah