Я читаю это. Какая польза от использования этого:
user&.address&.state
над
user.try(:address).try(:state)
Я все еще не понимаю.
Я читаю это. Какая польза от использования этого:
user&.address&.state
над
user.try(:address).try(:state)
Я все еще не понимаю.
&.
обычно короче try(...)
В зависимости от сценария это может сделать ваш код более читаемым.
&.
является стандартным Ruby, в отличие от try
Метод try
не определен в основной библиотеке Ruby, а скорее в библиотеке Rails. Когда вы не разрабатываете веб-приложение RoR, а вместо этого пишете, например. небольшие вспомогательные скрипты, это будет очень актуально.
(Например, я предпочитаю Ruby над Bash.)
&.
упрощает отладкуОператор безопасного обхода выдает ошибку, если вызывается несуществующий метод.
>> "s"&.glubsch
NoMethodError: undefined method `glubsch' for "s":String
Только на nil
он будет проявлять снисходительность:
>> nil&.glubsch
=> nil
Метод try
всегда будет возвращать nil
.
>> "s".try(:glubsch)
=> nil
Обратите внимание, что это относится к самым последним версиям Ruby и Rails.
Теперь представьте сценарий, в котором существует метод с именем glubsch
. Затем вы решите переименовать этот метод, но забудьте переименовать его в одном месте. (К сожалению, это может случиться с рубином...) С оператором безопасного обхода вы заметите ошибку почти сразу (как только эта строка кода будет выполнена в первый раз). Метод try
, однако, с радостью предоставит вам nil
, и вы получите сообщение об ошибке nil
где-то ниже по течению при выполнении программы. Выяснить, откуда пришел такой nil
, может быть сложно время от времени.
Неудача с быстрым и жестким с &.
делает отладку проще, чем беспечно возвращая nil
с помощью try
.
EDIT: Существует также вариант try!
(с помехой), который ведет себя так же, как &.
в этом отношении. Используйте это, если вам не нравится &.
.
Это было бы странно. Поскольку это будет неожиданным способом программирования, пожалуйста, сделайте это явным. Например, путем выделения двух случаев (реализованных или нет) с использованием respond_to?
и отклонением от него.
try
блочной формы?Вместо имени метода блок можно передать в try
. Блок будет выполнен в контексте получателя; и внутри блока не применяется смягчение. Таким образом, с помощью всего одного вызова метода он будет действовать так же, как &.
.
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch' for "s":String
Для более сложных вычислений вы можете предпочесть эту блочную форму, вводя множество локальных переменных. Например. цепь
foo.try{ glubsch.blam }.try{ bar }.to_s
позволяет foo
быть nil
, но требует foo.glubsch
для возврата значения nil
. Опять же, вы можете сделать то же самое с оператором безопасного обхода в более сжатой форме:
foo&.glubsch.blam&.bar.to_s
Использование блочной формы try
для сложных вычислений IMHO - запах кода, хотя, поскольку это затрудняет читаемость. Когда вам нужно реализовать сложную логику, введите локальные переменные с описательными именами и, возможно, используйте if
для ветки от случая nil
. Ваш код будет более удобным.
НТН!
Безопасная навигация почти в 4 раза быстрее, чем использование метода try из 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 } }
Выход
1.310000 0.000000 1.310000 ( 1.311835)
0.360000 0.000000 0.360000 ( 0.353127)