当我“包含”模块时,为什么Rails会尝试猜测文件名?

时间:2015-09-25 01:18:18

标签: ruby-on-rails ruby module

我有以下设置,其中一个类包含一个位于另一个文件中的模块

需要注意的关键是模块MyBar 生活在具有相似名称的文件中。它居住在my_foo.rb

my_foo.rb

module MyBar
  def self.test
    "This is a test string"
  end
end

some_class.rb

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

问题是

  1. 为什么Rails会这样做?似乎它假设太多了。我知道它已超过配置",但有几个正当理由要求文件名与模块名称不匹配。

  2. 如何覆盖此行为?

2 个答案:

答案 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。