我在app/presenters/my_namespace/base_presenter.rb
:
module MyNamespace
class BasePresenter
end
MY_SET = Set.new(['a', 'b', 'c'])
def self.my_method
true
end
end
当我在控制台中运行MyNamespace::MY_SET
或MyNamespace::my_method
时,我得到一个未初始化的常量错误,但我可以执行MyNamespace::BasePresenter.new
。我做错了什么?
答案 0 :(得分:2)
我假设您正在Rails开发模式中尝试这一点。在这种模式下,所有常量(类,模块和常量)都按需加载。
当ruby遇到未定义的常量时,它会抛出一个错误,自动加载器拦截并尝试通过将其名称转换为路径来加载常量。
在您的情况下,自动加载器会尝试查找
MyNamespace::MY_SET
app/presenters/my_namespace.rb
中的app/presenters/my_namespace/base_presenter.rb
(失败)并且不知道您是否在MyNamespace::BasePresenter
中实际定义了它。但是,在您加载MyNamespace
(顺便说一下,正确的路径)之后,MyNamespace::MY_SET
,MyNamespace.my_method
和MyNamespace
已初始化并可用。
您需要做的是
a)正确定义module MyNamespace
MY_SET = Set.new(['a', 'b', 'c'])
def self.my_method
true
end
end
并将方法和常量移动到其定义:
应用程序/主持人/ my_namespace.rb
# note that I don't open module here,
# but use a constant to enable autoloading of MyNamespace module
class MyNamespace::BasePresenter
end
应用程序/主持人/ my_namespace / base_presenter.rb
BasePresenter
或
b)将所有方法/常量移动到MyNamespace::BasePresenter::MY_SET
类。由于它位于正确的路径上,因此常量module MyNamespace
class BasePresenter
MY_SET = Set.new(['a', 'b', 'c'])
def self.my_method
true
end
end
end
将起作用。
module MyNamespace
class BasePresenter
end
end
之间的区别
class MyNamespace::BasePresenter
end
和
MyNamespace
是在第一种情况下未定义module MyNamespace
时将定义它(MyNamespace
打开现有模块或定义新模块),但在第二种情况下,上述机制将尝试在某处加载uninitialized constant error MyNamespace
,如果失败,您将获得module MyNamespace
。
如果您将所有命名空间类定义为第一种情况(在module MyNamespace
class BasePresenter
end
end
内)
应用程序/主持人/ my_namespace / base_presenter.rb
MyNamespace
并且module MyNamespace
MY_SET = Set.new(['a', 'b', 'c'])
end
位于正确的位置,其中包含一些代码
应用程序/主持人/ my_namespace.rb
MyNamespace::BasePresenter
如果您的MyNamespace
将首先加载,它实际上会定义app/presenters/my_namespace.rb
并且您的require
将不会被加载(因为自动加载仅加载缺少的常量),您将会必须自己presenter = MyNamespace::BasePresenter.new
MyNamespace::MY_SET # boom, uninitialized constant error
。
class MyNamespace::BasePresenter
这里的解决方案是在1 正确的位置定义模块(自动加载知道如何查找)并使用{{1}}格式在其适当的位置定义命名空间类。
答案 1 :(得分:0)
该代码没有任何问题,这表明问题是加载(或重新加载)问题。如果安装了默认的spring gem,请停止并重新启动控制台和/或spring stop
。
答案 2 :(得分:0)
可能你没有要求set
宝石。类Set
在set
gem中定义。它是标准库的一部分,但不是Ruby核心的一部分。在这种情况下,BasePresenter
的创建成功,因为这是在MY_SET = Set.new(['a', 'b', 'c'])
之前完成的,这引发了错误。 MY_SET
和my_method
未定义,因为这些定义出现在违规行上或之后。
你需要这样做:
require "set"