Je suis tombé sur cette ligne de code ruby. Que signifie `` moyenne en cela ?
Réponses
Trop de publicités?Il est appelé la Sécurité de la Navigation de l'Opérateur. Introduit en Ruby 2.3.0, il vous permet d'appeler des méthodes sur des objets sans se soucier que l'objet peut être nil
(en Évitant undefined method for nil:NilClass
d'erreur), similaire à l' try
méthode dans les Rails.
Vous pouvez donc écrire
@person&.spouse&.name
au lieu de
@person.spouse.name if @person && @person.spouse
À partir de la Docs:
my_object.my_method
Cela envoie le my_method message à my_object. Tout l'objet peut être un récepteur, mais selon la méthode de la visibilité l'envoi d'un message peut soulever une NoMethodError.
Vous pouvez utiliser &. pour désigner un récepteur, puis my_method n'est pas appelé et le résultat est nul lorsque le récepteur est nul. Dans ce cas, l' les arguments de my_method ne sont pas évalués.
Remarque: Même si @Santosh a donné une claire et complète réponse, je voudrais ajouter un peu plus de fond et d'ajouter une remarque importante concernant son utilisation avec les variables d'instance.
Il est appelé "la Sécurité de la Navigation de l'Opérateur" (aka "Option de chaînage de l'opérateur", "Null-opérateur conditionnel", etc.). Matz semble l'appeler "solitaire" d'opérateur. Il a été introduit en Ruby 2.3. Il envoie une méthode à un objet que s'il n'est pas nil
.
Exemple:
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
"Cas limite" avec des variables locales:
Veuillez noter que le code ci-dessus utilise les variables d'instance. Si vous souhaitez utiliser la sécurité de la navigation de l'opérateur avec des variables locales, vous devrez vérifier que vos variables locales sont tout d'abord 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 est définie en premier ou le mettre à néant:
# 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
Méthode d'arrière-plan
Rails a try
méthode qui fait fondamentalement la même. Il utilise send
méthode interne pour appeler une méthode. Matz a suggéré qu'il est lent et cela devrait être intégré dans le langage.
De nombreux autres langages de programmation ont des caractéristiques similaires: Objective-C, Swift, Python, Scala, CoffeeScript, etc. Cependant, une syntaxe commune est - ?.
(question de point). Mais, cette syntaxe ne peut être adopté par Ruby. Parce qu' ?
a été autorisé dans les noms de méthode et donc, ?.
symbole de la séquence est déjà valable du code Ruby. Par exemple:
2.even?.class # => TrueClass
C'est pourquoi la communauté Ruby dû venir avec une syntaxe différente. C'était une discussion active et les 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 étudié différents cas de bord et la discussion est tout à fait utile. Si vous voulez aller à travers toutes les variantes et nuances de l'opérateur, veuillez voir cette fonctionnalité introduction de discussion sur officiel Ruby bug tracker.
Méfiez-vous! Si la sécurité de la navigation de l'opérateur est pratique il peut être aussi facile de tromper vous-même en changeant votre logique avec elle. Je recommande d'éviter l'utilisation de l'informatique 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?
renvoie la valeur true et str.empty?
n'est jamais appelée, provoquant l' puts
instruction à exécuter. Dans le deuxième exemple toutefois, str&.empty?
retourne nil qui est falsey et l' puts
déclaration n'est jamais exécutée.