在Rails 3中从lib文件夹加载模块/类的最佳方式是什么?
由于最新的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);
从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)
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]
来源:Rails 3 Quicktip:Autoload lib目录包括所有子目录,避免延迟加载
请注意,lib文件夹中包含的文件仅在服务器启动时加载。 如果你想舒适地自动加载这些文件,请阅读:Rails 3 Quicktip:在开发模式下自动重新加载库文件夹。 请注意,由于永久重新加载减慢了机器速度,因此这不适用于生产环境。
自动加载的东西的魔力
我认为控制文件夹自动加载的选项已经在其他答案中得到了充分的说明。 但是,如果其他人在加载时遇到问题,但是他们的自动加载路径已根据需要进行了修改,那么此答案试图解释此自动加载事件背后的神奇之处。
所以当从子目录加载东西时,您应该注意一个问题或约定。 有时Ruby / Rails的魔力(这次主要是Rails)会让人很难理解为什么会发生。 只有在模块名称对应于父目录名称时,才会加载在自动加载路径中声明的任何模块。 所以如果你尝试将lib/my_stuff/bar.rb
如下内容中:
module Foo
class Bar
end
end
它不会被自动加载。 然后再次如果您将父目录重命名为foo
从而将您的模块托管在路径: lib/foo/bar.rb
它会在你身边。 另一个选项是命名您想要通过模块名称自动加载的文件。 显然,只能有一个文件名称。 如果你需要将你的东西分成许多文件,你当然可以使用这个文件来需要其他文件,但是我不建议这样做,因为那么当你在开发模式下修改那些其他文件时,Rails不能自动地为你重新加载它们。 但是,如果您确实希望您可以通过模块名称来指定一个文件,然后指定使用该模块所需的实际文件。 所以你可以有两个文件: lib/my_stuff/bar.rb
和lib/my_stuff/foo.rb
,前者与上述相同,后者包含一行: require "bar"
,这将起到相同的作用。
PS我觉得不得不增加一件更重要的事情。 最近,每当我想在lib目录中需要自动加载的东西时,我倾向于开始思考,如果这是我实际为此项目开发的东西(通常是这样,它可能有一天变成许多项目或git子模块等使用的“静态”代码片段,在这种情况下,它肯定应该在lib文件夹中),那么它的位置可能根本就不在lib文件夹中。 也许它应该在应用程序文件夹下的子文件夹中·我有一种感觉,这是新的轨道做事的方式。 显然,无论你在哪里自动加载你放入东西的路径,都可以使用同样的魔法,所以这对于这些东西来说是很好的。 无论如何,这只是我对这个问题的想法。 你可以自由地不同意。 :)
更新:关于魔术的类型..
Severin在他的评论中指出,核心“自动加载模块机制”肯定是Ruby的一部分,但自动加载路径的东西不是。 你不需要Rails来autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar")
。 当你第一次尝试引用模块Foo时,它会为你加载。 然而,Rails所做的是让我们尝试从注册文件夹中自动加载内容,并且已经以这样的方式实现,它需要假设关于命名约定的一些事情。 如果它没有像那样实现,那么每当你引用一些目前没有加载的东西时,它将不得不遍历所有自动加载文件夹中的所有文件,并检查它们中是否包含你想要引用的内容。 这反过来会打破自动加载和自动重新加载的想法。 但是,通过这些约定,它可以从模块/类中扣除您尝试加载可能定义的位置并加载该位置。
上一篇: Best way to load module/class from lib folder in Rails 3?