我有以下设置,其中一个类包含一个位于另一个文件中的模块
需要注意的关键是模块MyBar
不生活在具有相似名称的文件中。它居住在my_foo.rb
。
module MyBar
def self.test
"This is a test string"
end
end
require 'my_foo'
class SomeClass
include MyBar
def initialize
puts MyBar.test
end
end
当我运行时,我得到NameError
NameError - uninitialized constant MyBar
看起来Rails试图变得聪明并且假设因为模块名称是MyBar
,它应该位于类似名为my_bar.rb
的文件中。
我尝试通过将名称更改为预期名称来测试此理论,并且它突然正常工作
my_foo.rb (renamed)-> my_bar.rb
问题是
为什么Rails会这样做?似乎它假设太多了。我知道它已超过配置",但有几个正当理由要求文件名与模块名称不匹配。
如何覆盖此行为?
答案 0 :(得分:2)
这与自动加载在Rails中的工作方式有关。
当您尝试使用与文件名匹配且位于/lib/
目录下的新类/模块名称时,Rails仅自动加载。
要解决您的问题,您可以将my_foo.rb
文件放在/lib/
目录下,并按照以下要求进行操作:require 'lib/my_foo'
有关自动加载在Rails中如何工作的详细信息,请参阅Autoloading and Reloading Constants的Rails文档。
答案 1 :(得分:1)
由于各种原因app
目录未包含在导轨$LOAD_PATH
中(主要是在编辑内容时自动加载和重新加载类)。
如果要使用与文件名不匹配的常量,您希望在lib
目录中找到它们并要求它们(lib
中包含$LOAD_PATH
)。< / p>
如果您确实要在app
目录中包含文件,则可能需要尝试使用require Rails.root.join('app', 'models', 'my_foo.rb').to_s
。我不确定会破坏什么,你真的会反对rails convention。