我正在研究this pretty thorny problem并决定我可以动态创建一个继承自StandardError的类:
something = "JustForBelow"
error_class = "#{something}Error".constantize
error_class = StandardError.new
但是我得到了一个非常奇怪的错误(在我看来),这是:
Uninitialized constant JustForBelowError
我不是在那里初始化吗?
(基本上)当我尝试这个时出现相同的错误:
StandardError.const_get "#{something}Error"
# => NameError: uninitialized constant StandardError::JustForBelowClass
这感觉很奇怪,因为a)这些都是超级随机的名字;没有任何冲突,并且b)我很确定我在之前的第一个例子中使用了constantize。任何想法出了什么问题?
答案 0 :(得分:7)
ActiveSupport的constantize
方法只查找常量。它是const_get
的一个更高级的版本,它可以像遍历嵌套模块结构那样做得很好。
要创建新错误,您需要执行以下操作:
2.0.0-p247 :013 > Object.const_set("MyNewError", Class.new(StandardError))
=> MyNewError
2.0.0-p247 :014 > MyNewError.ancestors
=> [MyNewError, StandardError, Exception, Object, Kernel, BasicObject]
此时,您可以执行"MyNewError".constantize
并获取新的类对象。
修改强>
另请注意,第二个示例错误中的const_get
正在调用它所调用的命名空间。在这种情况下,在StandardError
的范围内。
例如,如果您有类结构:
module A
class B
CONSTANT = "hello world"
end
end
然后你可以通过"A::B::CONSTANT".constantize
或Object.const_get("A").const_get("B").const_get("CONSTANT")
来实现这一目标。同样的事情,只需要ActiveSupport就能做得更顺畅。
答案 1 :(得分:4)
对于任何想要查找的人,"如何在课程可能不存在时进行限制",有safe_constantize
,如果课程没有,则会返回nil
存在。它基本上只是rescue
constantize
左右。
'blargle'.safe_constantize # => nil
'UnknownModule'.safe_constantize # => nil
'UnknownModule::Foo::Bar'.safe_constantize # => nil
答案 2 :(得分:1)
如果你这样做,你会初步确定它:
class JustForBelowError < StandardError ; end
something = "JustForBelow"
error_class = "#{somestring}Error".constantize
error_class = StandardError.new
如果您希望能够使用constantize
“访问”常量,则需要定义常量。