在Rails 3中从lib文件夹加载模块/类的最佳方法?

既然最新的Rails 3版本不是自动加载lib和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:自动加载lib目录包括所有子目录,避免延迟加载

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

自动加载的东西的魔力

我认为控制文件夹自动加载的选项已经在其他答案中得到了充分的说明。 但是,如果其他人遇到麻烦的东西,虽然他们已经根据需要修改了自动加载path,但是这个答案试图解释这个自动加载的东西背后的神奇。

所以当从子目录加载东西时,应该注意一个问题或约定。 有时Ruby / Rails的魔力(这次主要是Rails)会让人很难理解为什么会发生。 在自动加载path中声明的任何模块只有在模块名称对应于父目录名称时才会被加载。 所以如果你尝试把lib/my_stuff/bar.rb如下lib/my_stuff/bar.rb话:

 module Foo class Bar end end 

它不会被自动加载。 然后再次,如果你重命名父目录为foo因此托pipe你的模块的path: lib/foo/bar.rb 它会在你身边。 另一个选项是命名您想要通过模块名称自动加载的文件。 那么显然只能有一个这个名字的文件。 如果你需要将你的东西分成许多文件,你当然可以使用这个文件来需要其他文件,但是我不build议这样做,因为在开发模式下,当你修改其他文件时,Rails不能自动地重新加载它们给你。 但是,如果你真的希望你可以有一个文件的模块名称,然后指定使用模块所需的实际文件。 所以你可以有两个文件: lib/my_stuff/bar.rblib/my_stuff/foo.rb ,前者和上面相同,后者只包含一行: require "bar" ,而且工作原理是一样的。

PS我觉得不得不增加一个更重要的事情。 最近,每当我想在lib目录下需要自动加载的东西的时候,我倾向于开始思考,如果这是我实际为这个项目而开发的东西(通常情况下,它可能有一天变成在许多项目或git子模块中使用的代码的“静态”片段,在这种情况下,它肯定应该在lib文件夹中),那么也许它的位置根本不在lib文件夹中。 也许它应该在应用程序文件夹下的子文件夹·我有一种感觉,这是新的轨道做事情。 很明显,无论你在哪里自动加载你放入东西的path,同样的魔法都可以工作,所以对这些东西来说很好。 无论如何,这只是我对这个问题的想法。 你可以自由地不同意。 🙂


更新:关于魔术的types

正如Severin在他的评论中指出的,核心“自动加载模块机制”当然是Ruby的一部分,但自动加载path的东西不是。 你不需要Rails来autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") 。 而当你尝试第一次引用模块Foo时,它会为你加载。 然而,Rails所做的是让我们尝试从注册文件夹中自动加载内容,并且已经以这样的方式实现,它需要假设一些关于命名约定的内容。 如果没有这样的实现,那么每当你引用一些目前没有加载的东西的时候,它将不得不遍历所有自动加载文件夹中的所有文件,并检查它们是否包含你想要引用的内容。 这反过来将打败自动加载和自动加载的想法。 但是,通过这些约定,它可以从模块/类中扣除您尝试加载可能已定义的地方,并加载该地址。

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

  • “ config.autoload_paths ”方法:只在加载一个只在一个地方定义的类时才有效。 如果某个类已经在其他地方定义了,那么就不能通过这个方法重新加载它。

  • “ config / initializer / load_rb_file.rb ”方法:始终工作! 无论目标阶级是新阶级还是现有阶级的“公开阶级”或“猴子派对”,它总能奏效!

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

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

 config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"] 

在我的情况下,我试图直接在lib目录下加载一个文件。

在application.rb中…

 require '/lib/this_file.rb' 

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

 require './lib/this_file.rb' 

和rails完美加载文件。

我仍然很漂亮,我不知道为什么这个工程,但它的作品。 如果有人想向我解释,我会很感激:希望这可以帮助任何人。

我有同样的问题。 这是我如何解决它。 解决scheme加载lib目录和所有子目录(不仅是直接的)。 当然,你可以在所有目录中使用它。

 # application.rb config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += Dir["#{config.root}/lib/**/"] 

config.autoload_paths不适用于我。 我以其他方式解决

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

 Dir["lib/**/*.rb"].each do |path| require_dependency path end 

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

 require 'mymodule' 

在model.rb文件的顶部。

有几个原因,你可能有问题从lib加载 – 这里看到的细节 – http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • 修复自动加载path
  • 线程安全相关
  • 命名相关

拼写正确的文件名。

认真。 我和class级争斗了一个小时,因为class级是Governance :: ArchitectureBoard,文件在lib / governance / architecture_baord.rb(在“board”中转置了O和A)

回想起来似乎是显而易见的,但那是魔鬼跟踪下来的。 如果这个类没有在Rails期望的基于类名的文件中定义,那么根本就不会find它。