Risposte:
Si chiama Safe Navigation Operator. Introdotto in Ruby 2.3.0, ti consente di chiamare metodi su oggetti senza preoccuparti che l'oggetto possa essere nil
(Evitare un undefined method for nil:NilClass
errore), simile al try
metodo in Rails .
Quindi puoi scrivere
@person&.spouse&.name
invece di
@person.spouse.name if @person && @person.spouse
Dai documenti :
my_object.my_method
Questo invia il messaggio my_method a my_object. Qualsiasi oggetto può essere un destinatario ma, a seconda della visibilità del metodo, l'invio di un messaggio può generare un NoMethodError.
Puoi usare &. per designare un ricevitore, quindi my_method non viene invocato e il risultato è zero quando il ricevitore è zero. In tal caso, gli argomenti di my_method non vengono valutati.
Nota: anche se @Santosh ha dato una risposta chiara e completa, vorrei aggiungere un po 'più di background e aggiungere una nota importante relativa al suo utilizzo con variabili non di istanza.
Si chiama " Operatore di navigazione sicura " ( noto anche come "Operatore di concatenamento opzionale", "Operatore nullo-condizionato", ecc .). Matz sembra chiamarlo "operatore solitario". È stato introdotto in Ruby 2.3 . Invia un metodo a un oggetto solo se non lo è nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Nota: il codice sopra utilizza le variabili di istanza. Se si desidera utilizzare un operatore di navigazione sicura con variabili locali, è necessario verificare prima che le variabili locali siano definite.
# `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
Per risolvere questo problema, controlla se la variabile locale è definita per prima o impostala su zero:
# 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 ha un try
metodo che sostanzialmente fa lo stesso. Usa il send
metodo internamente per chiamare un metodo. Matz ha suggerito che è lento e questa dovrebbe essere una funzionalità linguistica integrata.
Molti altri linguaggi di programmazione hanno funzionalità simili: Obiettivo C, Swift, Python, Scala, CoffeeScript, ecc. Tuttavia, una sintassi comune è ?.
(punto interrogativo). Ma questa sintassi non può essere adottata da Ruby. Perché ?
era consentito nei nomi dei metodi e quindi, la ?.
sequenza di simboli è già un codice Ruby valido. Per esempio:
2.even?.class # => TrueClass
Ecco perché la comunità di Ruby ha dovuto elaborare una sintassi diversa. E 'stata una discussione attiva e diverse opzioni sono stati considerati ( .?
, ?
, &&
, etc.). Ecco un elenco di alcune considerazioni:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Mentre scelgono la sintassi, gli sviluppatori hanno esaminato diversi casi limite e la discussione è abbastanza utile da affrontare. Se vuoi esaminare tutte le varianti e le sfumature dell'operatore, consulta questa discussione di introduzione della funzione sul tracker dei problemi di Ruby ufficiale.
.?
e sono state prese in considerazione altre opzioni, ma è &.
stata scelta! Quindi, funzionerà solo &.
.
&.
e non .?
, mia cattiva. Aggiornato la mia risposta. Grazie per il testa a testa!
user.?profile
dovrebbe essere user&.profile
(impossibile modificarlo da solo poiché è solo una modifica di 1 carattere!).
Diffidare! Sebbene l'operatore di navigazione sicura sia conveniente, può anche essere facile indurti a cambiare la logica con esso. Raccomando di evitarne l'uso nel controllo del flusso. Esempio:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
Nel primo esempio, str.nil?
restituisce true
e str.empty?
non viene mai chiamato, causando l' puts
esecuzione dell'istruzione. Nel secondo esempio, tuttavia, str&.empty?
restituisce nil
che è falso e l' puts
affermazione non viene mai eseguita.
str.nil?
è vera (come dici tu) il che significa str.empty?
che in realtà non verrà chiamato affatto (è così che funziona l' ||
operatore). Il resto della tua affermazione è corretta.
puts "hello" unless str&.present?
(binari solo per il metodo attuale?)
utilizzato per il controllo zero, come ad esempio in kotlin e swift; con Object -> Swift e Kotlin
model = car?.model
questo modello può essere nullo (Swift) o null (Kotlin) se non abbiamo definito il valore del modello nella classe di auto. usiamo quella e commerciale invece del punto interrogativo in rubino
model = car&.model
se usi car.model senza e commerciale e se il modello è zero il sistema non può continuare a funzionare.
try!
metodo, nontry