web-dev-qa-db-fra.com

Quelle est la différence entre `try` et` & .` (opérateur de navigation sécurisée) en Ruby

Voici mon 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>

Je pensais que &. est un raccourci pour .try mais je suppose que je me suis trompé. Quelqu'un peut-il m'indiquer la bonne direction en ce qui concerne ce qui me manque?

J'ai l'impression que ce n'est pas lié à Ruby. Du raisin peut-être? Bien que je ne comprenne pas comment cela pourrait être.

15
Adrien

&. fonctionne comme #try!, pas #try.

Et voici la description de #try! (from documentation ):

Identique à #try, mais déclenchera une exception NoMethodError si la réception n'est pas nulle et n'implémente pas la méthode essayée.

En gros, cela vous évite d’appeler une méthode sur nil, mais si un objet est présenté, il essaiera d’appeler sa méthode comme d’habitude.

La citation provient de la documentation Rails, il est donc important de souligner que Ruby ne fournit pas #try; il est fourni par Rails, ou plus précisément ActiveSupport. L'opérateur de navigation safe (&.) est toutefois une fonctionnalité de langage présentée dans Ruby 2.3.0.

32
Danil Speransky

La méthode try ignore beaucoup de choses, elle donne un coup de pouce et l'appelle un jour si les choses ne fonctionnent pas.

L'option de navigation conditionnelle & permet uniquement de bloquer les appels sur des objets nil. Tout le reste est considéré comme valide et se poursuivra avec toutes les conséquences, exceptions incluses.

10
tadman

J'arrive à la fête un peu tard ici, les autres réponses ont expliqué comment cela fonctionne, mais je voulais ajouter quelque chose que les autres réponses n'ont pas couvert.

Votre question demande Quelle est la différence entre try et &. dans Ruby . Ruby étant le mot clé ici.

La plus grande différence est que try n'existe pas en Ruby, c'est une méthode fournie par Rails. vous pouvez voir ceci ou vous-même si vous faites quelque chose comme ceci dans la console Rails: 

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

Cependant, si vous faites la même chose dans la console irb, vous obtiendrez: 

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

Le &. fait partie de la bibliothèque standard Ruby et est donc disponible dans tout projet Ruby, pas seulement dans Rails.

3
John Hayes-Reed

d'accord avec @Redithion dans la section commentaire

L'opérateur de navigation sécurisée (&.) En Ruby

L'opérateur de navigation sûr renvoie nil si une méthode est appelée sur un objet nil. Avant cela, si une méthode est appelée sur un objet nil, une erreur est générée comme indiqué ci-dessous.

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

Pourquoi avons-nous besoin d'une navigation sûre?

Plusieurs fois, nous n’obtenons pas d’objet à cause de valeurs d’entrée incorrectes. Dans ce cas, si nous procédons en appelant des méthodes qui attendent comme nous avons un objet, le code peut être cassé si l'objet devient nil.

Pour éviter ce cas, une navigation sécurisée est introduite. Cela garantit que notre code ne sera pas cassé même si l’objet sur lequel la méthode est appelée est nil objet. Cela devrait être utilisé lorsque nous sommes capables de recevoir un objet nil lorsque l'appel de la méthode échoue.

Exemples

Imaginez que vous avez un compte qui a un propriétaire et que vous voulez obtenir l’adresse du propriétaire. Si vous voulez être en sécurité et ne pas risquer une erreur Nil, écrivez quelque chose comme ce qui suit.

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

C'est vraiment verbeux et ennuyeux à taper. ActiveSupport inclut la méthode try qui a un comportement similaire (mais avec quelques différences clés qui seront discutées plus tard):

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

Il accomplit la même chose - il retourne l'adresse ou nil si une valeur de la chaîne est nulle. Le premier exemple peut également renvoyer false si, par exemple, le propriétaire est défini sur false.

En utilisant &.

Nous pouvons réécrire l'exemple précédent en utilisant l'opérateur de navigation sécurisée:

account&.owner&.address
1
Mayur Shah