错误类似于NameError: uninitialized constant Foo::Bar
(当Bar
不是Foo
的后代时)。
我知道它与加载(自动加载?)常量有关,而且我 * 觉得 * lib/
内部的任何内容都可以安全地不使用::
作为前缀,因为它是自动加载的(或其他)。
我刚刚遇到的一个例子是这样的:
- 应用程序/资产/类/基类.rb*
class BaseClass
end
- 应用程序/资产/部分模块/部分类.rb*
module SomeModule
class SomeClass < BaseClass
end
end
我正在运行一个规范,并得到“加载[文件]时发生错误":NameError: uninitialized constant SomeModule::SomeClass::BaseClass
.
现在,我知道它试图在SomeModule::SomeClass
中查找BaseClass
。但这在几个小时前还在工作,然后在没有对这些文件进行更改后停止。
所以,我可以只添加一个::
,然后使用class SomeClass < ::BaseClass
,但不明白为什么感觉不好,然后我想,我需要一直用::
填充我所有的代码吗?
1条答案
按热度按时间wn9m85ua1#
什么时候需要在Ruby常量前面加上“::“?
当你引用一个常量时,Ruby会在当前的模块嵌套中寻找它。
模块嵌套主要通过使用
module
和class
关键字打开类/模块来设置。如果在那里没有找到它,它将在模块嵌套中继续向上,直到它到达main,如果到那时仍然没有找到常量,你将得到一个丢失常量的错误。
这个错误可能会让人有些困惑,因为消息包含了模块巢状结构,而这个模块巢状结构是它开始寻找常数的位置。
通过给一个常量加上前缀
::
,可以显式地告诉Ruby从顶级名称空间解析该常量:在大多数情况下,这并不是绝对必要的,但是显式引用您自己的命名空间(依赖项)之外的常量是一个很好的做法。
那么为什么我的代码停止工作了呢?
如果没有一个实际的可复制的例子,这几乎是不可能的。这可能是“程序员相关的问题”(你搞砸了,移动/删除/重命名文件),也可能是使用中的自动加载器的问题。经典的自动加载器更容易出现错误行为,因为它的monkeypatch
Object#constant_missing
的方式。