Réponses:
Il est appelé l'opérateur de navigation sécurisée. Introduit dans Ruby 2.3.0, il vous permet d'appeler des méthodes sur des objets sans vous soucier que l'objet puisse être nil
(Éviter une undefined method for nil:NilClass
erreur), similaire à la try
méthode de Rails .
Pour que tu puisses écrire
@person&.spouse&.name
au lieu de
@person.spouse.name if @person && @person.spouse
À partir des documents :
my_object.my_method
Cela envoie le message my_method à my_object. Tout objet peut être un récepteur, mais selon la visibilité de la méthode, l'envoi d'un message peut déclencher une NoMethodError.
Vous pouvez utiliser &. pour désigner un receveur, alors my_method n'est pas invoqué et le résultat est nul lorsque le receveur est nul. Dans ce cas, les arguments de my_method ne sont pas évalués.
Remarque: Même si @Santosh a donné une réponse claire et complète, je voudrais ajouter un peu plus de contexte et ajouter une note importante concernant son utilisation avec des variables non-instance.
Il est appelé « opérateur de navigation sécurisée » ( alias «opérateur de chaînage facultatif», «opérateur conditionnel nul», etc. ). Matz semble l'appeler "opérateur solitaire". Il a été introduit dans Ruby 2.3 . Il envoie une méthode à un objet uniquement si ce n'est pas le cas nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Veuillez noter que le code ci-dessus utilise des variables d'instance. Si vous souhaitez utiliser un opérateur de navigation sécurisé avec des variables locales, vous devrez d'abord vérifier que vos variables locales sont définies.
# `user` local variable is not defined previous
user&.profile
# This code would throw the following error:
NameError: undefined local variable or method `user' for main:Object
Pour résoudre ce problème, vérifiez si votre variable locale est définie en premier ou définissez-la sur nil:
# Option 1: Check the variable is defined
if defined?(user)
user&.profile
end
# Option 2: Define your local variable. Example, set it to nil
user = nil
user&.profile # Works and does not throw any errors
Rails a une try
méthode qui fait essentiellement la même chose. Il utilise une send
méthode en interne pour appeler une méthode. Matz a suggéré qu'il était lent et que cela devrait être une fonctionnalité de langage intégrée.
De nombreux autres langages de programmation ont des fonctionnalités similaires: Objective C, Swift, Python, Scala, CoffeeScript, etc. Cependant, une syntaxe commune est ?.
(point de question). Mais, cette syntaxe n'a pas pu être adoptée par Ruby. Parce que cela ?
était autorisé dans les noms de méthode et donc, la ?.
séquence de symboles est déjà un code Ruby valide. Par exemple:
2.even?.class # => TrueClass
C'est pourquoi la communauté Ruby a dû proposer une syntaxe différente. Ce fut une discussion active et différentes options ont été envisagées ( .?
, ?
, &&
, etc.). Voici une liste de quelques considérations:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Lors du choix de la syntaxe, les développeurs ont examiné différents cas limites et la discussion est assez utile à parcourir. Si vous souhaitez parcourir toutes les variantes et nuances de l'opérateur, veuillez consulter cette discussion d'introduction des fonctionnalités sur le suivi des problèmes Ruby officiel.
.?
et d'autres options ont été envisagées, mais elles ont &.
été choisies! Donc, seul &.
fonctionnera.
&.
et non .?
, mon mal. J'ai mis à jour ma réponse. Merci pour l'information!
user.?profile
devrait être user&.profile
(je n'ai pas pu le modifier moi-même car il ne s'agit que d'une modification d'un caractère!).
Se méfier! Bien que l'opérateur de navigation sécurisé soit pratique, il peut également être facile de vous inciter à changer votre logique avec lui. Je recommande d'éviter son utilisation dans le contrôle de flux. Exemple:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
Dans le premier exemple, str.nil?
retourne true
et str.empty?
n'est jamais appelé, ce qui entraîne l' puts
exécution de l' instruction. Dans le deuxième exemple cependant, str&.empty?
renvoie nil
ce qui est faux et l' puts
instruction n'est jamais exécutée.
str.nil?
c'est vrai (comme vous le dites), ce qui signifie str.empty?
ne sera pas du tout appelé (c'est ainsi que fonctionne l' ||
opérateur). Le reste de votre déclaration est correct.
puts "hello" unless str&.present?
(rails uniquement pour la méthode actuelle?)
il a utilisé pour un contrôle nul, comme dans kotlin et swift Par exemple; avec Object -> Swift et Kotlin
model = car?.model
ce modèle peut être nul (Swift) ou nul (Kotlin) si nous n'avons pas défini la valeur du modèle dans la classe de voiture. nous utilisons cette esperluette au lieu du point d'interrogation en rubis
model = car&.model
si vous utilisez car.model sans esperluette et si le modèle est nul, le système ne peut pas continuer à fonctionner.
try!
méthode, pastry