Я читаю это. Какая польза от использования этого:
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)