在Ruby中将字符串转换为变量名

6

我有变量

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

我想动态地改变这些变量的值。
 <% 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

变量没有被赋值。有没有办法动态地给变量赋值?


4
请使用数组(或哈希表)来完成这个任务。 - Nikita Rybak
3
参考 2530112 的回答,建议使用 instance_variable_set - Emilio Silva
1
在某些编程语言中,动态地创建变量名是可行的,包括 Ruby 在内,但这种做法已经逐渐失宠多年,并且主要被认为是一种好奇心。它会导致混淆,从而引起维护问题,所以避免这个问题并使用哈希表。如果变量名来自用户提供的输入,则可能会导致安全问题,或者如果一个名称与先前创建的变量发生冲突,则可能会导致奇怪的错误。 - the Tin Man
3个回答

4
我认为没有办法做到这一点。对于实例或类变量,可以这样做,但是对于局部变量,很少有必要这样做。
在您的情况下,您真的应该将数据存储在散列表中。而且,像这样的逻辑确实不适合erb。您需要像这样的内容:
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
可以使用eval做到,但你说得对,这种做法不应该被采用。使用哈希表(hash)代替是更好的解决方案。 - the Tin Man
1
或者你可以将这个块传递给 inject{|hash,day|hash.merge(day=>0)} - zetetic

2

现在,我知道这个问题有点老了,但是有一种更简单的方法来做到这一点,就是使用标准的Ruby send方法。实际上,这是让Ruby在元编程世界中如此敏捷的方法之一。

这实际上是我在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

它是DRY的,非常易于理解。:)


0

这是对这个老问题的又一个答案。

在我的场景中,我想要计算一天在一组日期(day_array)中出现的次数。我不需要知道一天没有出现在 day_array 中,所以我没有像 gunn他的回答 中那样初始化了 days_count 哈希表。

这是我是如何做到的:

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

如果我在irb中复制并粘贴上述内容,则:
> count_days(%w[SU MO])
{"SU"=>1, "MO"=>1}

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

基本上,与之前的答案一致。但是,我认为再举一个例子也无妨。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接