Respostas:
É chamado de Operador de Navegação Segura. Introduzido no Ruby 2.3.0, permite chamar métodos em objetos sem se preocupar que o objeto possa ser nil
(Evitando um undefined method for nil:NilClass
erro), semelhante ao try
método no Rails .
Então você pode escrever
@person&.spouse&.name
ao invés de
@person.spouse.name if @person && @person.spouse
Dos documentos :
my_object.my_method
Isso envia a mensagem my_method para my_object. Qualquer objeto pode ser um receptor, mas, dependendo da visibilidade do método, o envio de uma mensagem pode gerar um NoMethodError.
Você pode usar &. para designar um receptor, então my_method não é chamado e o resultado é nulo quando o receptor é nulo. Nesse caso, os argumentos de my_method não são avaliados.
Nota: Embora o @Santosh tenha dado uma resposta clara e completa, gostaria de adicionar um pouco mais de background e uma nota importante sobre seu uso com variáveis que não são de instância.
É chamado de " Operador de Navegação Segura " ( também conhecido como "Operador de encadeamento opcional", "Operador nulo-condicional" etc. ). Matz parece chamá-lo de "operador solitário". Foi introduzido no Ruby 2.3 . Ele envia um método para um objeto apenas se não estiver nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Observe que o código acima usa variáveis de instância. Se você deseja usar um operador de navegação seguro com variáveis locais, deverá verificar se suas variáveis locais estão definidas primeiro.
# `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
Para corrigir esse problema, verifique se sua variável local está definida primeiro ou defina-a como nulo:
# 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
O Rails possui um try
método que basicamente faz o mesmo. Ele usa o send
método internamente para chamar um método. Matz sugeriu que é lento e esse deve ser um recurso de idioma interno.
Muitas outras linguagens de programação têm características semelhantes: Objective C, Swift, Python, Scala, CoffeeScript, etc. No entanto, uma sintaxe comum é ?.
(ponto de interrogação). Mas, essa sintaxe não pôde ser adotada pelo Ruby. Como ?
foi permitido nos nomes dos métodos e, portanto, a ?.
sequência de símbolos já é um código Ruby válido. Por exemplo:
2.even?.class # => TrueClass
É por isso que a comunidade Ruby teve que criar uma sintaxe diferente. Foi uma discussão activa e diferentes opções foram consideradas ( .?
, ?
, &&
, etc.). Aqui está uma lista de algumas considerações:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Ao escolher a sintaxe, os desenvolvedores analisaram diferentes casos extremos e a discussão é bastante útil. Se você deseja passar por todas as variantes e nuances do operador, consulte a discussão sobre introdução de recursos no rastreador oficial de problemas do Ruby.
.?
e outras opções foram consideradas, mas &.
foram escolhidas! Então, só &.
vai funcionar.
&.
e não.?
, meu mal. Atualizei minha resposta. Obrigado pela atenção!
user.?profile
deveria ser user&.profile
(não poderia editá-lo eu mesmo, pois é apenas uma edição de 1 caractere!).
Seja cauteloso! Embora o operador de navegação seguro seja conveniente, também pode ser fácil enganar-se a mudar sua lógica com ele. Eu recomendo evitar o uso dele no controle de fluxo. Exemplo:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
No primeiro exemplo, str.nil?
retorna true
e str.empty?
nunca é chamado, fazendo com que a puts
instrução seja executada. No segundo exemplo, no entanto, str&.empty?
retorna nil
false, e a puts
instrução nunca é executada.
str.nil?
seja verdadeira (como você diz), o que significa str.empty?
que na verdade não será chamado (é assim que o ||
operador funciona). O restante da sua declaração está correto.
puts "hello" unless str&.present?
(trilhos só para o presente método?)
usado para verificação nula, como em kotlin e swift Por exemplo; com Objeto -> Swift e Kotlin
model = car?.model
esse modelo pode ser nulo (Swift) ou nulo (Kotlin) se não tivermos definido o valor do modelo na classe de carro. usamos esse e comercial em vez de ponto de interrogação em rubi
model = car&.model
se usar car.model sem e comercial e se o modelo for nulo, o sistema não poderá continuar em execução.
try!
método, nãotry