Constantize引发未初始化的常量错误

时间:2013-12-19 17:55:47

标签: ruby-on-rails ruby metaprogramming

我正在研究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。任何想法出了什么问题?

3 个答案:

答案 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".constantizeObject.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

safe_constantize

答案 2 :(得分:1)

如果你这样做,你会初步确定它:

class JustForBelowError < StandardError ; end
something = "JustForBelow"
error_class = "#{somestring}Error".constantize
error_class = StandardError.new

如果您希望能够使用constantize“访问”常量,则需要定义常量。