我有一堆我想在命名空间中定义的模块,我把它们放在初始化器中,但是我得到了一个'错误的常量名'例外:
# 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
是空的,我不确定是什么错。
答案 0 :(得分: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
。
这不会重新定义它或任何东西,只需打开它以在其命名空间中添加新类。注意我是如何从const_set
中删除Object和Foobar并使用Ruby的%w[]
表示法来定义字符串数组,现在不需要to_s
和camelize
。
此外,它不适合你的原因是在常量名称中使用冒号以及通过执行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,前面的示例也会起作用。
答案 1 :(得分:2)
您的常量名称包含冒号。这是不允许的常量名称。