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

Sas*_*sha 6 ruby metaprogramming ruby-on-rails

我正在研究这个非常棘手的问题,并决定我可以通过这样做动态创建一个继承自StandardError的类:

something = "JustForBelow"
error_class = "#{something}Error".constantize
error_class = StandardError.new
Run Code Online (Sandbox Code Playgroud)

但是我得到了一个非常奇怪的错误(在我看来),这是:

Uninitialized constant JustForBelowError
Run Code Online (Sandbox Code Playgroud)

我不是在那里初始化它吗?

(基本上)当我尝试这个时出现相同的错误:

StandardError.const_get "#{something}Error"
# => NameError: uninitialized constant StandardError::JustForBelowClass
Run Code Online (Sandbox Code Playgroud)

这感觉很奇怪,因为a)这些都是超级随机的名字; 没有任何冲突,并且b)我很确定我在之前的第一个例子中使用了constantize.有什么想法会出错吗?

csc*_*eid 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]
Run Code Online (Sandbox Code Playgroud)

此时,您可以执行"MyNewError".constantize并获取新的类对象.

编辑 另请注意,const_get在第二个示例中,错误是查看调用它的命名空间.在那种情况下,在StandardError范围内.

例如,如果您有类结构,如:

module A
  class B
    CONSTANT = "hello world"
  end
end
Run Code Online (Sandbox Code Playgroud)

然后你就可以通过这种"A::B::CONSTANT".constantize方式实现目标Object.const_get("A").const_get("B").const_get("CONSTANT").同样的事情,只需要ActiveSupport就能做得更顺畅.


d3v*_*kit 6

对于任何试图找到“当类可能不存在时我如何保持不变”的人来说safe_constantizenil如果类不存在,它将返回。它本质上只是一个rescue围绕constantize.

'blargle'.safe_constantize  # => nil
'UnknownModule'.safe_constantize  # => nil
'UnknownModule::Foo::Bar'.safe_constantize  # => nil
Run Code Online (Sandbox Code Playgroud)

safe_constantize