2011-01-08 11 views
5

mam zmienneKonwersja ciąg do nazwy zmiennej w ruby ​​

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

Chcę zmienić wartości tych zmiennych dynamicznie.

<% 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 

Wartość nie jest przydzielana. Czy istnieje sposób na dynamiczne przypisanie wartości do zmiennej?

+4

Do, do, używaj do tego tablic (lub skrótów). –

+3

Odpowiedź na [2530112] (http://stackoverflow.com/questions/2530112) powinna pomóc, zaleca 'instance_variable_set'. –

+1

Dynamiczne tworzenie nazwy zmiennej w locie jest możliwe w niektórych językach, w tym także w Ruby, ale od lat traci na popularności i jest uważane za ciekawość. Prowadzi to do zamieszania, które prowadzi do problemów konserwacyjnych, więc obejść problem i użyć hasha. Może to również prowadzić do problemów z bezpieczeństwem, jeśli nazwy zmiennych pochodzą z danych dostarczonych przez użytkownika lub mogą spowodować dziwne błędy, jeśli nazwa zderzy się z wcześniej utworzoną zmienną. –

Odpowiedz

3

Nie sądzę, że istnieje sposób, aby to zrobić. Istnieje zmienna instancji lub klasy, ale w przypadku zmiennych lokalnych bardzo rzadko istnieje taka potrzeba.

W twoim przypadku naprawdę powinieneś mieć dane w haszowaniu. Również taka logika naprawdę nie należy do erb. Chcesz coś takiego:

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

Jest to możliwe przy użyciu eval, ale masz rację mówiąc, że nie należy tego robić w ten sposób. Używanie skrótu jest lepszym rozwiązaniem. –

+1

Lub możesz przekazać ten blok do 'inject':' {| hash, day | hash.merge (day => 0)} ' – zetetic

2

Teraz wiem, że to Cuestión jest nieco stary, ale jest łatwiejszy sposób, aby to zrobić i za pomocą standart Ruby wysłać metody. Jest to jedna z metod, która czyni Ruby tak elastycznym w świecie metaprogramowania.

# 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 

To suche i bardzo łatwy do zrozumienia: ustawienie config używam w aplikacji Rails

To jest rzeczywiście. :)

0

Jeszcze jedna odpowiedź na to stare pytanie.

W moim scenariuszu chciałem policzyć, ile razy dziennie pojawił się w tablicy dni (day_array). Nie musiałem wiedzieć, czy dzień nie pojawił się w day_array, więc nie zainicjowałem skrótu days_count jako gunn w his answer.

Oto jak to zrobiłem:

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 

Gdybym skopiuj i wklej powyższy w IRB, a następnie:

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

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

Zasadniczo, zgodnie z wcześniejszymi odpowiedziami. Ale myślałem, że dodatkowy przykład nie zaszkodzi.