Cosa fa &. (punto e commerciale) significa in Ruby?

Mi sono imbattuto in questa riga di codice ruby. Cosa fa &. significa in questo?

 @object&.method 

Si chiama Safe Navigation Operator. Introdotto in Ruby 2.3.0, consente di chiamare i metodi sugli oggetti senza preoccuparsi che l’object possa essere nil (Evitando un undefined method for nil:NilClass errore undefined method for nil:NilClass ), simile al metodo try 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 object può essere un ricevitore 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 è nullo quando il ricevitore è nullo. In tal caso, gli argomenti di my_method non vengono valutati.

Nota: anche se @Santosh ha fornito una risposta chiara e completa, vorrei aggiungere un po ‘di background e aggiungere una nota importante riguardo il suo utilizzo con variabili non di istanza.


Si chiama ” Safe Navigation Operator ” ( “Operatore di concatenamento opzionale”, “Operatore non condizionato”, ecc .). Matz sembra chiamarlo “operatore solitario”. È stato introdotto in Ruby 2.3 . Invia un metodo a un object solo se non è nil .

Esempio:

 # Call method `.profile` on `user` only if `user` is not `nil` @user&.profile # Equivalent to unless @user.nil? @user.profile end 

“Caso limite” con variabili locali:

Si prega di notare, il codice sopra utilizza variabili di istanza. Se si desidera utilizzare un operatore di navigazione sicuro con variabili locali, è necessario verificare che le variabili locali siano definite per prime.

 # `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 è stata definita per prima o impostata 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 

Metodo di fondo

Rails ha try metodo che fondamentalmente fa lo stesso. Usa internamente il metodo send per chiamare un metodo. Matz ha suggerito che è lento e questa dovrebbe essere una funzionalità di linguaggio incorporata.

Molti altri linguaggi di programmazione hanno caratteristiche simili: Objective C, Swift, Python, Scala, CoffeeScript, ecc. Tuttavia, una syntax comune è ?. (punto interrogativo). Ma questa syntax non può essere adottata da Ruby. Perché ? era permesso 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 syntax diversa. È stata una discussione triggers e sono state considerate diverse opzioni ( .? , ? , && , ecc.). 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 

Durante la scelta della syntax, gli sviluppatori hanno esaminato diversi casi limite e la discussione è abbastanza utile da seguire. Se vuoi esaminare tutte le varianti e le sfumature dell’operatore, consulta questa discussione introduttiva sulle funzionalità del tracker ufficiale di Ruby.

Diffidare! Anche se l’operatore di navigazione sicura è comodo, può anche essere facile ingannare te stesso nel cambiare la tua logica con esso. Raccomando di evitare l’uso di esso nel controllo del stream. 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? ritorna vero e str.empty? non viene mai chiamato, causando l’esecuzione dell’istruzione puts . Nel secondo esempio, tuttavia, str&.empty? restituisce nil che è falso e l’istruzione puts non viene mai eseguita.