在 Rails 3中将 lib 添加到‘ config.autoload_path’并不会自动加载我的模块

我将一个文件名 g.rb 放在 Rails.root/lib侧的文件夹中 文件内容如下:

module Google
end

然后我加上

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

到我的 Rails.root/config/application.rb

但是,当我尝试从 rails console调用 Google 时,会抛出一个异常。只有在执行 require 'google'时才会消除异常。 为什么? 我的文件不应该是自动加载的,我不应该访问模块没有任何额外的 require语句?

37904 次浏览

我发现了一件有趣的事。为了让 Rails 自动加载我的类,类名应该符合文件名和文件夹结构。 例如,如果我想让 Google 模块自动加载,我必须把它放在 google.rb中,直接放在/lib 下面(如果我指定自动加载来自/lib)。 如果我想自动加载 Google::Docs,那么我要么把它放在 google.rbgoogle/docs.rb

我刚才也遇到了同样的问题,我的“解决方案”(或者更确切地说是变通方法)是手动要求在 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

我的下一步将是按照您提到的将文件分类到模块文件夹中。

这是因为自动加载的要点是 没有“要求”事先做好一切准备(启动惩罚)。根据需要/引用加载类。为了做到这一点,您需要一些方法来知道在哪里查找类。否则,您必须提前加载 autoload 目录中的每个文件,以查看声明了哪些类。这是一种权衡,但是需要提前做好一切(就像马尔巴克建议的那样)不是自动加载。 您可以使用 Ruby 提供的 autoload 命令,它有两个参数,要加载的模块(在您的例子中是: Google) ,第二个参数是 filename,如果 lib 在您的加载路径中($:) ,则为 g.rb。请参阅 Ruby 文档了解自动加载。

在 Heroku 上运行模块时,我遇到了类似的问题。除了 Stephen c 提到的自动加载变数命名原则之外,我发现模块代码必须是 require,这是由于 Heroku 上的 Rails 生产环境假设了 threadsafe(尽管在我的 production.rb配置文件中已经注释掉了 threadsafe)一旦我在调用模块 include之前对模块文件进行了 require处理,一切就开始工作了。

require 'mymodule'
include Mymodule

请看看 这篇优秀的文章关于模块在 Heroku 正确加载的主题(生产)。

我最近发现了这个溶液

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

第一个 config 调用引导 Rail 自动加载 app/model 目录的所有子目录 现在我可以自动加载/app/model/sub _ directory/model. rb 了 (方便组织有大量代码的应用程序)

第二个 config 调用会导致 Rail 自动加载 lib/extons 目录

希望这能帮上忙

注意: 我相信这是轨道3具体

config.autoload_paths改为 config.eager_load_paths

(基于 Rails 问题 # 6850在 Rails 3.2控制台中从 lib 目录强制重载)