Respuestas:
Se llama el operador de navegación segura. Introducido en Ruby 2.3.0, le permite invocar métodos en objetos sin preocuparse de que el objeto pueda ser nil
(evitando un undefined method for nil:NilClass
error), similar al try
método en Rails .
Entonces puedes escribir
@person&.spouse&.name
en vez de
@person.spouse.name if @person && @person.spouse
De los documentos :
my_object.my_method
Esto envía el mensaje my_method a my_object. Cualquier objeto puede ser un receptor pero, dependiendo de la visibilidad del método, enviar un mensaje puede generar un NoMethodError.
Puedes utilizar &. para designar un receptor, entonces my_method no se invoca y el resultado es nulo cuando el receptor es nulo. En ese caso, los argumentos de my_method no se evalúan.
Nota: Aunque @Santosh dio una respuesta clara y completa, me gustaría agregar más antecedentes y una nota importante sobre su uso con variables que no son de instancia.
Se llama " Operador de navegación segura " ( también conocido como "Operador de encadenamiento opcional", "Operador condicional nulo", etc. ). Matz parece llamarlo "operador solitario". Fue introducido en Ruby 2.3 . Envía un método a un objeto solo si no lo es nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Tenga en cuenta que el código anterior usa variables de instancia. Si desea utilizar un operador de navegación seguro con variables locales, deberá verificar que sus variables locales se definan primero.
# `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
Para solucionar este problema, verifique si su variable local se define primero o configúrela en 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 tiene un try
método que básicamente hace lo mismo. Utiliza el send
método internamente para llamar a un método. Matz sugirió que es lento y que esta debería ser una función de lenguaje incorporada.
Muchos otros lenguajes de programación tienen características similares: Objetivo C, Swift, Python, Scala, CoffeeScript, etc. Sin embargo, una sintaxis común es ?.
(punto de pregunta). Pero, esta sintaxis no pudo ser adoptada por Ruby. Debido a que ?
estaba permitido en los nombres de métodos y, por lo tanto, la ?.
secuencia de símbolos ya es un código Ruby válido. Por ejemplo:
2.even?.class # => TrueClass
Es por eso que la comunidad Ruby tuvo que proponer una sintaxis diferente. Fue una discusión activa y se consideraron diferentes opciones ( .?
, ?
, &&
, etc.). Aquí hay una lista de algunas consideraciones:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Al elegir la sintaxis, los desarrolladores observaron diferentes casos límite y la discusión es bastante útil. Si desea ver todas las variantes y matices del operador, consulte esta discusión de introducción de características en el rastreador oficial de problemas de Ruby.
.?
y se consideraron otras opciones, ¡pero &.
se eligió! Entonces, solo &.
funcionará.
&.
y no .?
, mi mal. Actualicé mi respuesta. ¡Gracias por el aviso!
user.?profile
debería ser user&.profile
(¡no podría editarlo yo mismo, ya que es solo una edición de 1 carácter!).
¡Sé cauteloso! Aunque el operador de navegación segura es conveniente, también puede ser fácil engañarse para cambiar su lógica. Recomiendo evitar su uso en el control de flujo. Ejemplo:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
En el primer ejemplo, str.nil?
devuelve true
y str.empty?
nunca se llama, lo puts
que hace que se ejecute la instrucción. Sin embargo, en el segundo ejemplo, str&.empty?
devuelve el nil
cual es falsey, y la puts
declaración nunca se ejecuta.
str.nil?
es verdadero (como usted dice), lo que significa str.empty?
que en realidad no se llamará en absoluto (así es como funciona el ||
operador). El resto de su declaración es correcta.
puts "hello" unless str&.present?
(carriles sólo para el presente método?)
se usaba para verificación nula, como en kotlin y swift Por ejemplo; con Objeto -> Swift y Kotlin
model = car?.model
este modelo puede ser nulo (Swift) o nulo (Kotlin) si no hemos definido el valor del modelo en la clase de automóvil. usamos ese signo en lugar de signo de interrogación en rubí
model = car&.model
si usa car.model sin ampersand y si el modelo es nulo, el sistema no puede continuar ejecutándose.
try!
método, notry