3 ответов:
он называется оператором безопасной навигации. Введенный в Ruby 2.3.0, он позволяет вызывать методы на объектах, не беспокоясь о том, что объект может быть
nil(избегаяundefined method for nil:NilClassошибка), аналогичноtryметод в Rails.так что вы можете написать
@person&.spouse&.nameвместо
@person.spouse.name if @person && @person.spouseС Docs:
my_object.my_methodэто отправляет сообщение my_method в my_object. Любой объект может быть приемником, но в зависимости от видимости метода отправка сообщения может вызвать NoMethodError.
вы можете использовать &. назначить приемника, то заканчивается не вызывается и результат равен нулю, когда приемник равен нулю. В этом случае доводы заканчивается не оцениваются.
Примечание: хотя @Santosh дал четкий и полный ответ, я хотел бы добавить еще немного фона и добавить важное замечание относительно его использования с переменными без экземпляра.
это называется "Оператор Безопасной Навигации" (aka "необязательный оператор цепочки", "нулевой условный оператор" и т. д.). МАЦ, кажется, называет его "одиноким оператором". Это было введено в 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способ фон
рельсов
tryметод, который в основном делает то же самое. Он используетsendметод внутренне для вызова метода. Матц предложил что это медленно и это должно быть встроенной функцией языка.многие другие языки программирования имеют аналогичную функцию: Objective C, Swift, Python, Scala, CoffeeScript и т. д. Однако общим синтаксисом является
?.(точка вопрос). Но этот синтаксис не может быть принят Руби. Потому что?было разрешено в имена методов и, таким образом,?.последовательность символов уже является допустимым кодом 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.
будьте осторожны! Хотя оператор безопасной навигации удобен, также может быть легко обмануть себя, изменив свою логику с его помощью. Я рекомендую избегать использования его в управлении потоком. Пример:
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?возвращает truestr.empty?никогда не вызывается, причинивputsинструкция для выполнения. Во втором примере, однако,str&.empty?возвращает nil, который является falsey, иputsутверждение не выполняется.
Comments