ruby - ejemplos - ¿Por qué es mejor la navegación segura que usar try en Rails?
ruby on rails tutorial (2)
(1) &.
es generalmente más corto que try(...)
Dependiendo del escenario, esto puede hacer que su código sea más legible.
(2) &.
Es estándar Ruby, a diferencia de try
El método try
no está definido en una biblioteca central de Ruby, sino en una biblioteca de Rails. Cuando no esté desarrollando una aplicación web de RoR, sino que esté escribiendo, por ejemplo, pequeños scripts de ayuda, esto se volverá relevante bastante rápido. (Prefiero Ruby sobre Bash, por ejemplo.)
(3) &.
facilita la depuración
El operador de recorrido seguro emitirá un error si se invoca un método inexistente.
>> "s"&.glubsch
NoMethodError: undefined method `glubsch'' for "s":String
Sólo en nil
se comportará con indulgencia:
>> nil&.glubsch
=> nil
El método try
siempre devolverá nil
.
>> "s".try(:glubsch)
=> nil
Tenga en cuenta que este es el caso de las versiones más recientes de Ruby y Rails.
Ahora imagine un escenario donde exista un método llamado glubsch
. Luego decide cambiar el nombre de ese método, pero olvide cambiarlo en un solo lugar. (Lamentablemente, eso puede suceder con ruby ...) Con el operador de cruce seguro, notará el error casi de inmediato (tan pronto como esa línea de código se ejecute por primera vez). Sin embargo, el método de try
le proporcionará un nil
y obtendrá un error relacionado nil
algún punto posterior en la ejecución del programa. Determinar de dónde vino ese nil
puede ser difícil a veces.
Fallando rápido y duro con &.
hace que la depuración sea más fácil que devolver nilmente alegremente con try
.
EDITAR: También está la variante de try!
(con una explosión) que se comporta igual que &.
a este respecto. Usa eso si no te gusta &.
.
(4) ¿Qué pasa si no me importa si un método se implementa o no?
Eso sería extraño. Ya que esa sería una forma inesperada de programación, por favor hazla explícita. Por ejemplo, mediante la implementación de los dos casos (implementados o no) utilizando respond_to?
y se ramifican fuera de eso.
(5) ¿Qué pasa con la forma de bloque de try
?
En lugar de un nombre de método, se puede pasar un bloque a try
. El bloque se ejecutará en el contexto del receptor; y dentro del bloque no se aplica indulgencia. Por lo tanto, con una sola llamada a un método, se comportará de la misma manera que &.
.
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch'' for "s":String
Para cálculos más complejos, es posible que prefiera esta forma de bloque en lugar de introducir muchas variables locales. Por ejemplo, una cadena de
foo.try{ glubsch.blam }.try{ bar }.to_s
permitiría que foo
sea nil
pero requiere que foo.glubsch
devuelva un valor no nil
. Por otra parte, puede hacer lo mismo con el operador de cruce seguro de una manera más concisa:
foo&.glubsch.blam&.bar.to_s
Sin embargo, el uso de la forma de bloque de try
para cálculos complejos IMHO es un olor a código, porque impide la legibilidad. Cuando necesite implementar una lógica compleja, introduzca variables locales con nombres descriptivos y tal vez use una if
para derivar un caso nil
. Tu código será más mantenible.
HTH!
Estoy leyendo this ¿Cuál es el beneficio de usar esto?
user&.address&.state
terminado
user.try(:address).try(:state)
Todavía no lo entiendo.
(6) Velocidad
La navegación segura es casi 4 veces más rápida que usar el método try de activesupport
require ''active_support/all''
require ''benchmark''
foo = nil
puts Benchmark.measure { 10_000_000.times { foo.try(:lala) } }
puts Benchmark.measure { 10_000_000.times { foo&.lala } }
Salida
1.310000 0.000000 1.310000 ( 1.311835)
0.360000 0.000000 0.360000 ( 0.353127)