2016-03-10 12 views
18

In Rails, è possibile fare hash.try(:[], :key) che aiuta se hash è potenzialmente nil. Esiste una versione equivalente per l'utilizzo del nuovo operatore di navigazione sicuro Ruby 2.3 &. con []?Navigazione sicura equivalente a Rails try for hashes

+0

Possibile duplicato di [Rubino - hash multidimensionale di accesso e di evitare l'accesso nil oggetto] (https://stackoverflow.com/questions/10130726/ruby-access-multidimensional-hash-and-avoid-access-nil-object) – kolen

risposta

22

&. non equivale a Rails' try, ma è possibile utilizzare &. per gli hash. Basta usarlo, niente di speciale.

hash[:key1]&.[](:key2)&.[](:key3) 

Anche se io non lo farei.

+2

Buon punto con '& .' e' try' sono diversi. Stavo solo pensando che "hash" sia "nullo". Quello che ho finito per usare era 'hash &. [] (: Chiave)' –

+0

Questo funziona solo per Ruby 2.3+? – bbozo

+0

@bbozo Sì. '& .' è stato introdotto in Ruby 2.3. – sawa

2

risposta accettata non rappresenteranno quando hash è nulla ...

È possibile riscrivere ciò che avete utilizzando l'operatore nav sicuro prima della .try e che lavorerà

hash&.try(:[], :key)

ma si può anche usare:

http://ruby-doc.org/core-2.3.0_preview1/Hash.html#method-i-dig

A w ay si potrebbe fare questo su un hash è facendo ...

hash&.dig(:key1, :key2 ...) 

che restituirà nullo se qualsiasi recuperare chiave non è presente.

{ key1: { key2: 'info' } } 

sarebbero tornati 'info'

{ key1: { wrong_key: 'info' } } 

sarebbe tornare nil

20

Pre Rubino 2.3

Io di solito ha avuto qualcosa come questo messo nel mio intializer:

Class Hash 
    def deep_fetch *args 
     x = self 
     args.each do |arg| 
     x = x[arg] 
     return nil if x.nil? 
     end 
     x 
    end 
end 

e poi

response.deep_fetch 'PaReqCreationResponse', 'ThreeDSecureVERes', 'Message', 'VERes', 'CH', 'enrolled' 

in un caso strambo.

Il consenso generale nella comunità sembra essere quello di evitare sia provare e l'operatore solitario &.

Rubino 2.3 e successivamente

C'è Hash#dig metodo ormai che fa proprio questo:

Recupera l'oggetto valore corrispondente a ciascun oggetto chiave ripetutamente.

h = { foo: {bar: {baz: 1}}} 

h.dig(:foo, :bar, :baz)   #=> 1 
h.dig(:foo, :zot)     #=> nil 

http://ruby-doc.org/core-2.3.0_preview1/Hash.html#method-i-dig

+1

Sembra sospettosamente simile nei casi d'uso a 'dig', introdotto in 2.3 come' & .'. Qualche differenza? –

+0

Infatti, grazie! :) – bbozo

+4

IMHO questa dovrebbe essere la risposta accettata. –

1

Mentre hash&.[](:key) è elegante per gli rubyist addestrato, mi basta usare hash && hash[:key] come si legge meglio e in modo più intuitivo per il programmatore viene dopo di me, che non può essere come familiarità con la complessità del rubino. Alcuni caratteri extra nella base di codice possono a volte risparmiare un sacco di googling per qualcun altro.

(Dato il contesto che si desidera utilizzare questo è in una dichiarazione condizionale, ovviamente.)