2011-10-05 7 views
32

En Ruby, que estoy tratando de escribir una línea que utiliza una variable si se ha establecido, de otro modo por defecto a algún valor:Ruby: La manera más concisa de usar una variable si es que existe, en caso contrario utilice el valor predeterminado

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

podría escribir el código como esto:

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

Pero esto es bastante detallado, y yo estoy tratando de escribir de la manera más concisa posible. ¿Cómo puedo hacer esto?

+0

¿qué pasa si MY_VAR = ""? – tokland

Respuesta

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

N.B. Esto es ligeramente incorrecto (si el hash puede contener el valor nil) pero dado que ENV contiene solo cadenas, probablemente sea lo suficientemente bueno.

-1

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

De esta manera se mantiene el .is_set? método.

+0

¿'is_set?' Es un método ruby? Pensé que lo inventé porque no sabía el nombre del método que estaba pidiendo. – Andrew

+0

Al menos en mi versión de ruby ​​no hay is_set ?, ¿hay ENV.has_key? –

28

La forma más fiable para un hash general es para preguntar si tiene la clave:

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

Si no se preocupan por nil o false valores (es decir, desea tratarlos lo mismo que " no existe "), entonces el enfoque undur_gongor de es bueno (esto también debe estar bien cuando h es ENV):

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

Y si desea permitir nil a estar en su hash, pero pretender que no está allí (es decir, a nil valor es el mismo que "no existe") al tiempo que permite una false en su Hash:

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

Al final, realmente depende de su intención precisa y se debe elegir el enfoque que coincide con su intención. La elección entre if/else/end y ? : es, por supuesto, una cuestión de gusto y "conciso" no significa "menor cantidad de caracteres", así que siéntase libre de utilizar un bloque ternario o if según lo desee.

+0

+1: Respuesta que cubre todo. –

+0

Dittos @undur_gongor. Gracias por ser exhaustivo! – theUtherSide

17
hash.fetch(key) { default_value } 

devolverá el valor si es que existe, y volver default_value si no existe la clave.

+7

O 'hash.fetch (key, default_value)' si el valor predeterminado no depende de la clave. –

+0

@mu es demasiado corto: Sí. Por lo general, estoy haciendo 'hash.fetch (clave) {raise" # {key.inspect} ¡no existe! " } ', así que no estaba 100% seguro del orden correcto cuando hay dos parámetros. –

+3

Yo (como casi todos los demás parece) tienden a olvidar que 'fetch' incluso existe así que +1 para usar toda la API. –

2

Aunque no es relevante en el ejemplo específico que proporcionó, ya que realmente está preguntando sobre las claves hash, no sobre las variables, Ruby ofrece una forma de verificar la definición de la variable. Usar la palabra clave defined? (que no es un método, pero una palabra clave, ya que necesita un tratamiento especial por el intérprete), así:

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

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

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

defined? blahblahblah 
    #=> nil 

De ahí que podría hacer:

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

Por lo que yo sé , esa es la única forma que no sea un feo bloque begin/rescue/end para definir una variable en la forma en que usted pregunta sin arriesgar un NameError. Como ya he dicho, esto no se aplica a los hashes desde:

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

i.e.está comprobando que se ha definido el método [] en lugar del par clave/valor para el que lo está utilizando.

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

'foobar' siendo el valor predeterminado si ENV['MY_VAR'] no está definido.

Cuestiones relacionadas