276

由于最新的 Rails 3 版本不再从 lib 中自动加载模块和类,那么加载它们的最佳方式是什么?

来自 github:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);
4

12 回答 12

252

从 Rails 2.3.9开始,config/application.rb您可以在其中指定包含要自动加载的文件的目录。

来自 application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
于 2010-07-28T19:48:05.970 回答
200
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

来源:Rails 3 Quicktip:自动加载 lib 目录,包括所有子目录,避免延迟加载

请注意,lib 文件夹中包含的文件仅在服务器启动时加载。如果您想舒适地自动重新加载这些文件,请阅读:Rails 3 快速提示:在开发模式下自动重新加载 lib 文件夹。请注意,这不适用于生产环境,因为永久重新加载会减慢机器速度。

于 2010-10-18T18:49:11.823 回答
84

自动加载东西的魔力

我认为控制完成自动加载内容的文件夹的选项已在其他答案中充分涵盖。但是,如果其他人虽然根据需要修改了自动加载路径,但在加载东西时遇到了问题,那么这个答案试图解释这个自动加载背后的魔力是什么。

因此,当涉及从子目录加载内容时,您应该注意一个问题或约定。有时 Ruby/Rails 的魔力(这次主要是 Rails)会让人很难理解为什么会发生某些事情。只有当模块名称对应于父目录名称时,才会加载自动加载路径中声明的任何模块。因此,如果您尝试输入以下内容lib/my_stuff/bar.rb

module Foo
  class Bar
  end
end

它不会自动加载。然后再一次,如果您将父目录重命名为foo因此将您的模块托管在 path: lib/foo/bar.rb。它会在那里为你服务。另一种选择是通过模块名称命名要自动加载的文件。显然,那个名称只能有一个文件。如果您需要将您的东西拆分成多个文件,您当然可以使用该文件来要求其他文件,但我不建议这样做,因为在开发模式下并且您修改这些其他文件时,Rails 无法自动执行为您重新加载它们。但是,如果您真的想要,您可以拥有一个模块名称的文件,然后指定使用该模块所需的实际文件。所以你可以有两个文件:lib/my_stuff/bar.rb并且lib/my_stuff/foo.rb前者与上面相同,后者包含一行:require "bar"这将是一样的。

PS我觉得有必要补充一件更重要的事情。最近,每当我想在 lib 目录中有一些需要自动加载的东西时,我倾向于开始思考,如果这是我实际上专门为这个项目开发的东西(通常是这样,可能有一天变成许多项目或 git 子模块等中使用的“静态”代码片段。在这种情况下,它肯定应该在 lib 文件夹中)那么它的位置可能根本不在 lib 文件夹中。或许应该在app文件夹下的子文件夹里·我有一种感觉,这是新的rails做事方式。显然,无论您在自动加载路径中放置您的东西的任何地方,同样的魔法都在发挥作用,因此这对这些东西有好处。无论如何,这只是我对这个问题的想法。你可以不同意。:)


更新:关于魔法的类型..

正如 severin 在他的评论中指出的那样,核心“自动加载模块机制”肯定是 Ruby 的一部分,但自动加载路径的东西不是。你不需要 Rails 来做autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). 当您第一次尝试引用模块 Foo 时,它将为您加载。然而,Rails 所做的是它为我们提供了一种尝试从注册文件夹中自动加载内容的方法,并且它已经以需要假设一些关于命名约定的方式实现。如果它没有像那样实现,那么每次您引用当前未加载的内容时,它都必须检查所有自动加载文件夹中的所有文件,并检查其中是否包含您要引用的内容。这反过来又会破坏自动加载和自动重新加载的想法。但是,有了这些约定,它可以从模块/类中扣除您尝试加载可能定义的位置并加载它。

于 2012-03-22T09:59:14.887 回答
42

警告:如果你想从你的'lib'文件夹加载'monkey patch'或'open class',不要使用'autoload'方法!!!

  • config.autoload_paths ” 方法:仅当您加载仅在一个地方定义的类时才有效。如果已经在其他地方定义了某个类,那么您不能通过这种方法再次加载它。

  • config/initializer/load_rb_file.rb ” 方法:总是有效!无论目标课程是新课程还是现有课程的“开放课程”或“猴子补丁”,它总是有效的!

有关更多详细信息,请参阅:https ://stackoverflow.com/a/6797707/445908

于 2013-01-08T06:52:32.773 回答
28

非常相似,但我认为这更优雅一点:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
于 2011-10-02T07:46:29.757 回答
18

就我而言,我试图直接在 lib 目录下加载一个文件。

在 application.rb...

require '/lib/this_file.rb' 

没有工作,即使在控制台中,然后当我尝试

require './lib/this_file.rb' 

并且rails完美地加载了文件。

我仍然很菜鸟,我不确定为什么这有效,但它有效。如果有人想向我解释,我将不胜感激:DI 希望这对任何人都有帮助。

于 2013-10-15T01:44:20.447 回答
7

我有同样的问题。这是我解决它的方法。该解决方案加载 lib 目录和所有子目录(不仅是直接目录)。当然,您可以将其用于所有目录。

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
于 2010-09-22T15:28:13.670 回答
5

config.autoload_paths 对我不起作用。我用其他方式解决

Ruby on rails 3 不会从 /lib 文件夹自动重新加载(自动加载)代码。我通过放入里面来解决它ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
于 2011-10-18T10:51:44.423 回答
5

从 开始Rails 5,建议将 lib 文件夹放在 app 目录下,或者为文件夹创建其他有意义的命名空间,如,services等,并将其放在 app 目录下,以便通过 rails 自动加载。presentersfeatures

请同时查看此GitHub 讨论链接

于 2018-03-02T11:25:20.377 回答
4

如果只有某些文件需要访问 lib 中的模块,只需在需要它的文件中添加 require 语句即可。例如,如果一个模型需要访问一个模块,则添加:

require 'mymodule'

在 model.rb 文件的顶部。

于 2010-07-31T01:27:15.607 回答
2

正确拼写文件名。

严重地。我和一个班级争了一个小时,因为班级是 Governance::ArchitectureBoard 并且文件在 lib/governance/architecture_baord.rb 中(在“board”中转置了 O 和 A)

回想起来似乎很明显,但这是魔鬼追踪的。如果类没有定义在 Rails 期望它基于修改类名的文件中,它根本不会找到它。

于 2017-10-19T16:00:55.430 回答
1

有几个原因可能会导致从 lib 加载时出现问题 - 请参阅此处了解详细信息 - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • 修复自动加载路径
  • 线程安全相关
  • 命名相关
  • ...
于 2013-04-20T10:23:33.333 回答