meta-ruby:如何动态调用作用域常量



假设我有一个类,比如:

class Person
  module Health
    GOOD = 10
    SICK = 4
    DEAD = 0
  end
end

我可以参考这样的健康码:Person::Health::GOOD。我想动态生成一个从数值映射回常量名称的哈希:

{ 10 => "GOOD",
   4 => "SICK",
   0 => "DEAD" }

为了动态地做到这一点,我提出了:

Person::Health.constants.inject({}) do |hsh, const|
  hsh.merge!( eval("Person::Health::#{const}") => const.to_s )
end

这是可行的,但我想知道是否有更好/更安全的方法。它在Rails应用程序中,虽然它离任何用户输入都不远,但eval仍然让我感到紧张。有更好的解决方案吗?

您可以为此使用constantsconst_get

ph = Person::Health # Shorthand
Hash[ph.constants(false).map { |c| [ph.const_get(c), c.to_s ] }]
# {10=>:GOOD, 4=>:SICK, 0=>:DEAD}

我将false添加到.constants中,以防止包含来自所包含模块的任何继承常量。例如,如果没有false,以下场景也将包括5 => "X"映射:

module A
  X = 5
end
class Person
  module Health
    include A        
    # ... 
  end
end
Hash[ph.constants.map { |c| [ph.const_get(c), c.to_s ] }]
# {10=>"GOOD", 4=>"SICK", 0=>"DEAD", 5=>"X"}

最新更新