2011-10-05 13 views
32

In Ruby, sto cercando di scrivere una riga che utilizza una variabile se è stato impostato, altrimenti di default per un certo valore:Rubino: Modo più conciso per utilizzare una variabile se esiste, altrimenti utilizzare il valore predefinito

myvar = # assign it to ENV['MY_VAR'], otherwise assign it to 'foobar' 

potrei scrivere questo codice come questo:

if ENV['MY_VAR'].is_set? #whatever the function is to check if has been set 
    myvar = ENV['MY_VAR'] 
else 
    myvar = 'foobar' 
end 

Ma questo è piuttosto prolisso, e sto cercando di scrivere nel modo più conciso possibile. Come posso fare questo?

+0

cosa succede se MY_VAR = ""? – tokland

risposta

44
myvar = ENV['MY_VAR'] || 'foobar' 

N.B. Questo è leggermente errato (se l'hash può contenere il valore nil) ma dal momento che ENV contiene solo stringhe probabilmente è abbastanza buono.

-1

myvar = ENV['MY_VAR'].is_set? ? ENV['MY_VAR'] : 'foobar'

In questo modo si mantiene il .is_set? metodo.

+0

Is 'is_set?' Un metodo ruby? Pensavo di averlo inventato perché non conoscevo il nome del metodo che stavo chiedendo. – Andrew

+0

Almeno nella mia versione di ruby ​​non c'è is_set ?, c'è un ENV.has_key? –

28

Il modo più affidabile per un Hash generale è quella di chiedere se ha la chiave:

myvar = h.has_key?('MY_VAR') ? h['MY_VAR'] : 'default' 

Se non si preoccupano nil o false valori (ad esempio si vuole trattare loro lo stesso come " non c'è "), allora l'approccio di undur_gongor è buono (questo dovrebbe anche essere bene quando h è ENV):

myvar = h['MY_VAR'] || 'foobar' 

E se si desidera consentire nil di essere nella vostra Hash, ma far finta che non ci sia (cioè a nil valore è lo stesso di "non c'è"), pur consentendo un false nel Hash:

myvar = h['MY_VAR'].nil?? 'foobar' : h['MY_VAR'] 

Alla fine in realtà dipende il vostro intento preciso e si dovrebbe scegliere l'approccio che corrisponde al tuo intento. La scelta tra if/else/end e ? : è, ovviamente, una questione di gusti e "concisa" non significa "numero minimo di caratteri", quindi sentiti libero di utilizzare un blocco ternario o if come desideri.

+0

+1: risposta che copre tutto. –

+0

Dittos @undur_gongor. Grazie per essere accurato! – theUtherSide

17
hash.fetch(key) { default_value } 

restituirà il valore se esiste, e restituire default_value se la chiave non esiste.

+7

Oppure 'hash.fetch (chiave, valore_predefinito)' se l'impostazione predefinita non dipende dalla chiave. –

+0

@mu è troppo breve: sì. Di solito sto facendo 'hash.fetch (chiave) {raise" # {key.inspect} non esiste! " } ', quindi non ero sicuro al 100% dell'ordine corretto quando ci sono due parametri. –

+3

I (come quasi tutti gli altri sembra) tendono a dimenticare che 'fetch' esiste anche in questo modo +1 per utilizzare l'intera API. –

2

Anche se non è pertinente nell'esempio specifico che hai dato dal momento che stai chiedendo veramente le chiavi hash, non le variabili, Ruby offre un modo per controllare la definizione delle variabili. Usa la parola chiave defined? (non è un metodo, ma una parola chiave in quanto ha bisogno di un trattamento speciale per l'interprete), in questo modo:

a = 1 
defined? a 
    #=> "local-variable" 

@a = 2 
defined? @a 
    #=> "instance-variable" 

@@a = 3 
defined? @@a 
    #=> "class-variable" 

defined? blahblahblah 
    #=> nil 

Quindi si potrebbe fare:

var = defined?(var) ? var : "default value here" 

Per quanto ne so , questo è l'unico modo diverso da un brutto begin/ blocco per definire una variabile nel modo in cui si chiede senza rischiare un NameError. Come ho detto, questo non si applica agli hash poiché:

hash = {?a => 2, ?b => 3} 
defined? hash[?c] 
    #=> "method" 

, ad es.stai verificando che il metodo [] sia definito piuttosto che la coppia chiave/valore che stai utilizzando per accedere.

0
myvar = ENV.fetch('MY_VAR') { 'foobar' } 

'foobar' essere il default se ENV['MY_VAR'] è disinserito.

Problemi correlati