2014-02-20 41 views
1

我有,我想在一个命名空间来定义模块的一堆,我把它们放在一个初始化,但我得到一个“错误常量名”例外:错误常量名Object.const_set嵌套模块

# this is a self-contained example 
require 'active_support/all' 
# ==> true 

[:baz, :qux].each do |name| 
    Object.const_set("FooBar::#{name.to_s.camelize}", Module.new { 
    define_singleton_method :my_awesome_static_method do |amount| 
     DoSomething.calculate(amount) 
    end 
    }) 
end 
# =NameError: wrong constant name FooBar::Baz 
# = from (irb):4:in `const_set' 
# = from (irb):4:in `block in irb_binding' 
# = from (irb):3:in `each' 
# = from (irb):3 
# = from /usr/local/var/rbenv/versions/2.0.0-p353/bin/irb:12:in `<main>' 

我认为我得到这个,因为初始化FooBar之前运行的定义,但问题是,如果我在这个初始化定义它,FooBar.constants是空的,我不知道什么是错的。

回答

3

总结你的代码在Foobar类或模块:

module Foobar 
    %w[Baz Qux].each do |name| 
    const_set(name, Module.new { 
     define_singleton_method :my_awesome_static_method do |amount| 
     DoSomething.calculate(amount) 
     end 
    }) 
    end 
end 

使用class Foobar如果它是一流的。

这不会重新定义它或任何东西,只要打开它在其命名空间中添加新的类。注意我是如何去除对象和Foobar的从const_set和使用Ruby的%w[]符号定义字符串数组,没有必要现在to_scamelize他们。

此外,它不适合你的原因是在常数名称中使用冒号以及通过执行Object.const_set而不是在Foobar上定义它们来定义Object上的常量。这也将起作用:

%w[Baz Qux].each do |name| 
    Foobar.const_set(name, Module.new { 
    define_singleton_method :my_awesome_static_method do |amount| 
     DoSomething.calculate(amount) 
    end 
    }) 
end 

假设Foobar已经定义好了,即使Foobar尚未加载,前面的例子仍然可以工作。

+0

我看,我有两件事情错了,'const_set'被发送到'FooBar',不'Object',并且名称不包括冒号。 – tlehman

2

你不变名称包含冒号。这是不允许的常数名称。