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

Vin*_*ent 271 module ruby-on-rails class autoload ruby-on-rails-3

由于最新的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);
Run Code Online (Sandbox Code Playgroud)

Slo*_*vic 249

从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)
Run Code Online (Sandbox Code Playgroud)

  • 如果你想要自动加载`app/lib`的整个子树,请注意@ thankful的答案. (7认同)

小智 198

# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Run Code Online (Sandbox Code Playgroud)

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

请注意,lib文件夹中包含的文件仅在服务器启动时加载.如果您希望舒适地自动加载这些文件,请阅读:Rails 3 Quicktip:在开发模式下自动重新加载lib文件夹.请注意,这不适用于生产环境,因为永久重新加载会降低计算机的速度.


Tim*_*imo 82

自动加载东西的神奇之处

我认为控制自动加载内容的文件夹的选项已经在其他答案中得到了充分的介绍.但是,如果其他人遇到麻烦,虽然他们已根据需要修改了自动加载路径,但这个答案试图解释这个自动加载的事情背后的魔力.

因此,当涉及从子目录加载东西时,你应该知道一个问题或一个约定.有时Ruby/Rails魔术(这次主要是Rails)可能会让人难以理解为什么会发生什么.仅当模块名称对应于父目录名称时,才会加载在自动加载路径中声明的任何模块.所以如果你试图加入lib/my_stuff/bar.rb类似的东西:

module Foo
  class Bar
  end
end
Run Code Online (Sandbox Code Playgroud)

它不会自动加载.然后再次重命名父目录,foo从而在路径中托管您的模块:lib/foo/bar.rb.它会在你身边.另一个选项是按模块名称命名要自动加载的文件.显然,那个名称只能有一个文件.如果你需要将你的东西拆分成许多文件,你当然可以使用那个文件来要求其他文件,但我不建议这样做,因为那时在开发模式下你修改那些其他文件然后Rails无法自动化为你重新加载它们.但是,如果您真的希望您可以通过模块名称拥有一个文件,然后指定使用该模块所需的实际文件.所以,你可以有两个文件:lib/my_stuff/bar.rblib/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所做的是它为我们提供了一种从注册文件夹中自动尝试和加载内容的方法,并且这种方式已经实现,它需要假设一些有关命名约定的内容.如果没有像那样实现,那么每次引用当前未加载的内容时,都必须遍历所有自动加载文件夹中的所有文件,并检查它们中是否包含您尝试引用的内容.这反过来会破坏自动加载和自动加载的想法.但是,有了这些约定,它可以从模块/类中扣除您尝试加载可能定义的位置并加载它.


Siw*_*申思维 41

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

  • " config.autoload_paths "方法:仅在加载仅在一个地方定义的类时才有效.如果已经在其他地方定义了某个类,则无法通过此方法再次加载它.

  • " config/initializer/load_rb_file.rb "方法:始终有效!无论目标类是新类还是现有类的"开放类"或"猴子补丁",它始终有效!

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

  • 这是理解的关键区别.谢谢你. (6认同)

Bri*_*ong 28

非常相似,但我觉得这更优雅一点:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
Run Code Online (Sandbox Code Playgroud)


Nic*_*Res 17

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

在application.rb中......

require '/lib/this_file.rb' 
Run Code Online (Sandbox Code Playgroud)

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

require './lib/this_file.rb' 
Run Code Online (Sandbox Code Playgroud)

和rails完美地加载文件.

我还是漂亮的菜鸟,我不知道为什么会这样,但它确实有效.如果有人想向我解释,我会很感激:DI希望这可以帮助某人.

  • 那是因为./lib/this_file.rb在当前目录中查找(在Rails控制台中,这将是您的Rails根目录),并且/lib/this_file.rb将其视为绝对路径.示例:./ lib/this_file.rb = /var/www/myrailsapp/lib/this_file.rb,/lib/this_file.rb = /lib/this_file.rb (2认同)

hju*_*ycz 7

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

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

  • 这具有完全破坏Rails命名空间约定的令人讨厌的副作用.如果定义Bar :: Foo的lib/bar/foo.rb出现在自动加载查找中定义Foo的lib/foo.rb之前,那么你会得到一些令人困惑的错误,如`Expected lib/bar/foo.rb来定义常量Foo`如果您尝试通过引用Foo常量来加载lib/foo.rb. (5认同)

msa*_*sa7 5

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

Ruby on rails 3不会自动从/ ​​lib文件夹重新加载(自动加载)代码.我把它解决了ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
Run Code Online (Sandbox Code Playgroud)


Ash*_*man 5

由于Rails 5,建议把lib文件夹的应用程序目录下或代替创建其他有意义的名字空间的文件夹servicespresentersfeatures等,并把它应用目录下自动加载的轨道。

请同时查看此GitHub 讨论链接