2011-01-08 23 views
5

que tienen las variablescadena Convertir a nombre de variable en rubí

<% mon_has_two_sets_of_working_hours = 0 %> 
<% tue_has_two_sets_of_working_hours = 0 %> 
<% wed_has_two_sets_of_working_hours = 0 %> 

que quieren cambiar los valores de estas variables de forma dinámica.

<% days_array = ['mon', 'tue', 'wed'] %> 

<% days_array.each do |day| %> 
    <% if condition? %> 
    # here i want to set %> 
    <% "#{day}__has_two_sets_of_working_hours" = 1 %> 
    end 
end 

El valor no se está asignando. ¿Hay alguna forma de asignar valor a la variable de forma dinámica?

+4

Haz, haz, utiliza matrices (o hashes) para eso. –

+3

La respuesta a [2530112] (http://stackoverflow.com/questions/2530112) debería ayudar, recomienda 'instance_variable_set'. –

+1

La creación dinámica de un nombre de variable sobre la marcha es factible en algunos idiomas, incluido Ruby, pero ha estado perdiendo popularidad durante años, y se considera una curiosidad sobre todo. Conduce a una confusión que conduce a problemas de mantenimiento, por lo tanto, evite el problema y use un hash. También puede provocar problemas de seguridad si los nombres de las variables provienen de una entrada proporcionada por el usuario, o podría causar errores extraños si un nombre colisionara con una variable creada anteriormente. –

Respuesta

3

No creo que haya una manera de hacer esto. Hay variables de instancia o de clase, pero con variables locales rara vez hay una buena necesidad.

En su caso, realmente debería tener los datos en un hash. Además, la lógica como esta realmente no pertenece a erb. ¿Quieres algo como:

working_hour_sets = %w[mon tue wed thu fri sat sun].inject({}) do |hash, day| 
    hash[day]=0; 
    hash 
end 
# puts working_hour_sets #=> {"wed"=>0, "sun"=>0, "thu"=>0, "mon"=>0, "tue"=>0, "sat"=>0, "fri"=>0} 

working_hour_sets.each do |day, value| 
    working_hour_sets[day] = 1 if condition? 
end 
+1

Es posible usar eval, pero tienes razón al decir que no debería hacerse de esa manera. Usar un hash es una mejor solución. –

+1

O podría pasar este bloque a 'inyectar':' {| hash, día | hash.merge (día => 0)} ' – zetetic

2

Ahora, sé que esta cuestion es un poco viejo, pero hay una manera más fácil de hacer esto y está utilizando el standart Rubí enviar método. Este es en realidad uno de los métodos que hace que Ruby sea tan ágil en el mundo de la metaprogramación.

Esto es en realidad un ajuste de configuración que uso en una aplicación Rails:

# In a YAML  
twitter: 
    consumer_key: 'CONSUMER-KEY' 
    consumer_secret: 'CONSUMER-SECRET' 
    oauth_token: 'OAUTH-KEY' 
    oauth_token_secret: 'OAUTH-SECRET' 

... 

# And in your file.rb 
config = YAML.load_file(Rails.root.join("config", "social_keys.yml"))[Rails.env]['twitter'] 

Twitter.configure do |twitter| 
    config.each_key do |k| 
    twitter.send("#{k}=", config[k]) 
    end 
end 

Es SECO y muy fácil de entender. :)

0

Otra respuesta a esta vieja pregunta.

En mi situación, quería contar cuántas veces al día apareció una serie de días (day_array). No necesitaba saber si un día no aparecía en day_array, por lo que no inicialicé el hash days_count como lo hizo gunn en his answer.

Así es como lo hice:

def count_days(day_array) 
    days_count = {} 
    day_array.each do |day| 
    days_count[day].nil? ? days_count[day] = 1 : days_count[day] = days_count[day] + 1 
    end 
    puts days_count 
end 

Si puedo copiar y pegar lo anterior en IRB, entonces:

> count_days(%w[SU MO]) 
{"SU"=>1, "MO"=>1} 

> count_days(%w[SU SU MO]) 
{"SU"=>2, "MO"=>1} 

Básicamente, en consonancia con las respuestas anteriores. Pero, pensé que un ejemplo adicional no podría doler.