在Rails 3中将lib添加到'config.autoload_paths'不会自动加载我的模块


73

我在副Rails.root/lib文件夹中放置了一个文件名g.rb。文件内容如下:

module Google
end

然后我添加

config.autoload_paths += %W(#{config.root}/lib #{Rails.root}/app/delayed_jobs)

给我 Rails.root/config/application.rb

但是,当我尝试从调用Google时rails console,会引发异常。只有我执行了,例外才会消失require 'google'。为什么?我的文件不应该自动加载require吗?我应该在没有任何其他语句的情况下访问模块吗?

Answers:


113

嗯,我发现了一件有趣的事。为了让Rails自动加载我的班级,班级名称应与文件名和文件夹结构兼容。例如,如果我想自动加载Google模块,则必须将它放在内google.rb,直接位于/ lib下(以防我从/ lib指定自动加载)。如果我想自动加载Google::Docs,则可以将其放置在内部google.rbgoogle/docs.rb


6
这是一个错误还是约定?
Blankman

8
我相信这是惯例。Rails采用常量名称,并从中创建路径。::为此变成了/。因此Google :: Docs变成了google / docs.rb。您可能会争论这样做的用处,但这是我对当前功能的理解。
本哈米尔

3
据我所知,这本身不是约定,这是Ruby解释器查找内容的方式
Ghoti,

1
哇,这只是发生在我身上。我不太在乎约定,可以重命名模块。我只是从未想过。+1。
squarism,2011年

3
这是Rails的约定,而不是Ruby的约定
Yarin

27

让我的模块在Heroku上运行时,我遇到了类似的问题。除了Stephen C声明的自动加载命名约定外,我发现模块代码必须require“ d”,这是threadsafe基于Rails在Heroku上的生产环境所做的假设(即使threadsafe在我的production.rb配置文件中已注释掉)。当我require在调用模块之前找到模块文件时include,一切开始正常工作。

require 'mymodule'
include Mymodule

请阅读这篇关于如何在Heroku(生产)中正确加载模块的优秀文章


+1这应该是公认的答案。该链接应该可以帮助任何人,线程安全实际上是我的问题。谢谢。
Erik B

24

这是因为自动加载的目的不是要“预先”要求所有东西(启动损失)。根据需要/引用加载类。为了做到这一点,您需要某种方式来知道在哪里寻找该类。否则,您必须预先加载autoload目录中的每个文件,才能查看声明了哪些类。这是一个折衷方案,但预先要求所有内容(如marbaq所建议的那样)不会自动加载。您可以使用Ruby提供的autoload命令,该命令带有两个参数,即要加载的模块(以符号表示,即:Google),第二个参数为文件名,如果lib位于您的文件名中则为g.rb。加载路径($ :)。有关自动加载的信息,请参见Ruby文档。


1
顺便说一句,约定说您应该将lib / g.rb重命名为lib / google.rb并继续使用。
斯蒂芬·C


1

我现在遇到了同样的问题,我的“解决方案”(或更确切地说,解决方法)是手动要求application.rb中的Rails.root / lib中的每个所需文件。

require 'lib/message'
require 'lib/store'
require 'lib/vault/vault.rb'
require 'lib/custom_loggers'

module MyApplication
  class Application < Rails::Application

正如您提到的,下一步是将模块文件夹中的文件分类。


嗨,@ morbaq,今天我遇到了同样的问题,您的解决方案运行良好,只是想说谢谢你:D
sameera207

-5

我最近找到了这个解决方案

config / application.rb

module AppName
  class Application < Rails::Application

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
    config.autoload_paths += Dir[Rails.root.join('app', 'lib', 'extensions')] 

  end
end

第一个配置调用使Rails自动加载app / models目录的所有子目录,因此现在我可以自动加载/app/models/sub_directory/model.rb(用于组织具有大型代码库的应用程序非常方便)

第二个配置调用导致Rails自动加载lib / extensions目录

希望这可以帮助

注意:我相信这是特定于Rails 3的

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.