Ответы:
Это называется оператор безопасной навигации. Представленный в Ruby 2.3.0, он позволяет вызывать методы для объектов, не беспокоясь о том, что объект может быть nil
(избегая undefined method for nil:NilClass
ошибки), подобно try
методу в Rails .
Так что вы можете написать
@person&.spouse&.name
вместо того
@person.spouse.name if @person && @person.spouse
Из документов :
my_object.my_method
Это отправляет сообщение my_method my_object. Любой объект может быть получателем, но в зависимости от видимости метода отправка сообщения может вызвать ошибку NoMethodError.
Вы можете использовать &. чтобы назначить получателя, тогда my_method не вызывается, и результат равен нулю, когда получатель равен нулю. В этом случае аргументы my_method не оцениваются.
Примечание. Несмотря на то, что @Santosh дал четкий и полный ответ, я хотел бы добавить еще немного фона и добавить важное примечание относительно его использования с переменными, не являющимися экземплярами.
Он называется « Оператор безопасной навигации » ( он же «Необязательный оператор цепочки», «Нулевой оператор» и т . Д. ). Мац, кажется, называет это «одиноким оператором». Он был представлен в Ruby 2.3 . Он отправляет метод к объекту, только если это не так nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Обратите внимание, что в приведенном выше коде используются переменные экземпляра. Если вы хотите использовать оператор безопасной навигации с локальными переменными, вы должны будете проверить, что ваши локальные переменные определены в первую очередь.
# `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
Чтобы устранить эту проблему, проверьте, определена ли ваша локальная переменная первой, или установите для нее значение 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 есть try
метод, который в основном делает то же самое. Он использует send
метод внутри для вызова метода. Мац предположил, что это медленно, и это должно быть встроенной функцией языка.
Многие другие языки программирования имеют аналогичную функцию: Objective C, Swift, Python, Scala, CoffeeScript и т. Д. Тем не менее, общий синтаксис ?.
(точка вопроса). Но этот синтаксис не может быть принят Ruby. Поскольку это ?
было разрешено в именах методов и, следовательно, ?.
последовательность символов уже является допустимым кодом Ruby. Например:
2.even?.class # => TrueClass
Вот почему сообществу Ruby приходилось придумывать другой синтаксис. Это было активное обсуждение и были рассмотрены различные варианты ( .?
, ?
, &&
и т.д.). Вот список некоторых соображений:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
При выборе синтаксиса разработчики смотрели на различные крайние случаи, и обсуждение довольно полезно пройти. Если вы хотите ознакомиться со всеми вариантами и нюансами оператора, ознакомьтесь с введением этой функции на официальном трекере проблем Ruby.
.?
, были рассмотрены и другие варианты, но &.
был выбран! Так что, только &.
сработает.
&.
и нет .?
, мой плохой. Обновил мой ответ. Спасибо за головы!
user.?profile
должно быть user&.profile
(не могу редактировать сам, так как это всего лишь 1 символ!).
Будьте осторожны! Хотя оператор безопасной навигации удобен, он также может легко обмануть себя и изменить свою логику. Я рекомендую избегать использования этого в контроле потока. Пример:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
В первом примере str.nil?
возвращает true
и str.empty?
никогда не вызывается, что приводит puts
к выполнению оператора. Однако во втором примере str&.empty?
возвращается значение nil
false, и puts
оператор никогда не выполняется.
str.nil?
верно (как вы говорите), что означает, str.empty?
что на самом деле вообще не будет вызываться (так ||
работает оператор). Остальная часть вашего утверждения верна.
puts "hello" unless str&.present?
(рельсы только для настоящего метода?)
он используется для проверки на ноль, например, в kotlin и swift; с объектом -> Свифт и Котлин
model = car?.model
эта модель может быть nil (Swift) или null (Kotlin), если мы не определили значение модели в классе автомобиля. мы используем этот амперсанд вместо знака вопроса в рубине
model = car&.model
если использовать car.model без амперсанда и если модель равна нулю, система не сможет продолжить работу.
try!
метод, а неtry