简体   繁体   English

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

[英]Best way to load module/class from lib folder in Rails 3?

Since the latest Rails 3 release is not auto-loading modules and classes from lib anymore, what would be the best way to load them? 由于最新的Rails 3版本不再从lib中自动加载模块和类,因此最好的加载方式是什么?

From github: 来自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); 

As of Rails 2.3.9 , there is a setting in config/application.rb in which you can specify directories that contain files you want autoloaded. 从Rails 2.3.9开始config/application.rb中存在一个设置,您可以在其中指定包含要自动加载的文件的目录。

From 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/**/"]

Source: Rails 3 Quicktip: Autoload lib directory including all subdirectories, avoid lazy loading 来源: Rails 3快速提示:自动加载包括所有子目录的lib目录,避免延迟加载

Please mind that files contained in the lib folder are only loaded when the server is started. 请注意,lib文件夹中包含的文件仅在服务器启动时加载。 If you want the comfort to autoreload those files, read: Rails 3 Quicktip: Auto reload lib folders in development mode . 如果您希望自动重新加载这些文件,请阅读: Rails 3快速提示:在开发模式下自动重新加载lib文件夹 Be aware that this is not meant for a production environment since the permanent reload slows down the machine. 请注意,这并不适合生产环境,因为永久性重新加载会降低机器的速度。

The magic of autoloading stuff 自动加载东西的魔力

I think the option controlling the folders from which autoloading stuff gets done has been sufficiently covered in other answers. 我认为其他答案已经充分介绍了控制从中完成自动加载的文件夹的选项。 However, in case someone else is having trouble stuff loaded though they've had their autoload paths modified as required, then this answer tries to explain what is the magic behind this autoload thing. 但是,如果有人根据需要修改了自动加载路径后却加载了麻烦的东西,那么此答案将试图解释自动加载背后的魔力是什么。

So when it comes to loading stuff from subdirectories there's a gotcha or a convention you should be aware. 因此,从子目录加载内容时,您应该知道一个陷阱或约定。 Sometimes the Ruby/Rails magic (this time mostly Rails) can make it difficult to understand why something is happening. 有时,Ruby / Rails的魔力(这次主要是Rails)可能使人们很难理解为什么发生了事情。 Any module declared in the autoload paths will only be loaded if the module name corresponds to the parent directory name. 仅当模块名称与父目录名称相对应时,才会加载在自动加载路径中声明的任何模块。 So in case you try to put into lib/my_stuff/bar.rb something like: 因此,如果您尝试将lib/my_stuff/bar.rb

module Foo
  class Bar
  end
end

It will not be loaded automagically. 它不会自动加载。 Then again if you rename the parent dir to foo thus hosting your module at path: lib/foo/bar.rb . 再一次,如果您将父目录重命名为foo从而将模块托管在路径: lib/foo/bar.rb It will be there for you. 它将为您服务。 Another option is to name the file you want autoloaded by the module name. 另一个选择是使用模块名称来命名要自动加载的文件。 Obviously there can only be one file by that name then. 显然,那时只有一个文件具有该名称。 In case you need to split your stuff into many files you could of course use that one file to require other files, but I don't recommend that, because then when on development mode and you modify those other files then Rails is unable to automagically reload them for you. 万一您需要将您的内容拆分为多个文件,您当然可以使用一个文件来要求其他文件,但是我不建议这样做,因为在开发模式下修改其他文件时,Rails无法自动进行为您重新加载。 But if you really want you could have one file by the module name that then specifies the actual files required to use the module. 但是,如果您确实想要,则可以在模块名称旁有一个文件,然后指定使用该模块所需的实际文件。 So you could have two files: lib/my_stuff/bar.rb and lib/my_stuff/foo.rb and the former being the same as above and the latter containing a single line: require "bar" and that would work just the same. 因此,您可能有两个文件: lib/my_stuff/bar.rblib/my_stuff/foo.rb ,前一个与上面相同,而后者只包含一行: require "bar"并且工作原理相同。

PS I feel compelled to add one more important thing. 附言:我感到不得不添加另一件重要的事情。 As of lately, whenever I want to have something in the lib directory that needs to get autoloaded, I tend to start thinking that if this is something that I'm actually developing specifically for this project (which it usually is, it might some day turn into a "static" snippet of code used in many projects or a git submodule, etc.. in which case it definitely should be in the lib folder) then perhaps its place is not in the lib folder at all. 最近,每当我想在lib目录中有需要自动加载的内容时,我就会开始思考,如果这是我真正为该项目专门开发的(通常是一天)变成许多项目或git子模块等中使用的“静态”代码段。在这种情况下,它绝对应该在lib文件夹中),那么它的位置可能根本不在lib文件夹中。 Perhaps it should be in a subfolder under the app folder· I have a feeling that this is the new rails way of doing things. 也许应该在app文件夹下的子文件夹中。我感觉这是新的Rails处理方式。 Obviously, the same magic is in work wherever in you autoload paths you put your stuff in so it's good to these things. 显然,无论您在何处放置自动加载路径,同样的魔力都在起作用,因此对这些事情都有利。 Anyway, this is just my thoughts on the subject. 无论如何,这只是我对这个问题的想法。 You are free to disagree. 您可以自由地不同意。 :) :)


UPDATE: About the type of magic.. 更新:关于魔术的类型

As severin pointed out in his comment, the core "autoload a module mechanism" sure is part of Ruby, but the autoload paths stuff isn't. 正如severin在他的评论中指出的那样,核心“自动加载模块机制”当然是Ruby的一部分,但是自动加载路径的内容却不是。 You don't need Rails to do autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") . 您不需要Rails来autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") And when you would try to reference the module Foo for the first time then it would be loaded for you. 当您第一次尝试引用模块Foo时,它将为您加载。 However what Rails does is it gives us a way to try and load stuff automagically from registered folders and this has been implemented in such a way that it needs to assume something about the naming conventions. 但是,Rails所做的是,它为我们提供了一种尝试从注册的文件夹中自动加载内容的方法,并且这种实现方式需要假设一些有关命名约定的方式。 If it had not been implemented like that, then every time you reference something that's not currently loaded it would have to go through all of the files in all of the autoload folders and check if any of them contains what you were trying to reference. 如果尚未实现,则每次引用当前未加载的内容时,都必须遍历所有自动加载文件夹中的所有文件,并检查其中是否包含您要引用的内容。 This in turn would defeat the idea of autoloading and autoreloading. 这反过来会破坏自动加载和自动重新加载的想法。 However, with these conventions in place it can deduct from the module/class your trying to load where that might be defined and just load that. 但是,有了这些约定,它可以从模块/类中扣除您尝试加载可能定义的位置并仅加载该内容的尝试。

Warning: if you want to load the 'monkey patch' or 'open class' from your 'lib' folder, don't use the 'autoload' approach !!! 警告:如果要从“ lib”文件夹中加载“ monkey patch”或“ open class”,请不要使用“ autoload”方法

  • " config.autoload_paths " approach: only works if you are loading a class that defined only in ONE place. config.autoload_paths ”方法:仅在加载仅在一个位置定义的类时有效。 If some class has been already defined somewhere else, then you can't load it again by this approach. 如果已经在其他地方定义了某个类,则无法通过这种方法再次加载它。

  • " config/initializer/load_rb_file.rb " approach: always works! config / initializer / load_rb_file.rb ”方法:总是有效! whatever the target class is a new class or an "open class" or "monkey patch" for existing class, it always works! 无论目标类是新类,还是现有类的“开放类”或“猴子补丁”,它始终有效!

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

非常相似,但是我认为这有点优雅:

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

In my case I was trying to simply load a file directly under the lib dir. 就我而言,我试图直接在lib目录下直接加载文件。

Within application.rb... 在application.rb中...

require '/lib/this_file.rb' 

wasn't working, even in console and then when I tried 即使在控制台中也无法正常工作,然后当我尝试

require './lib/this_file.rb' 

and rails loads the file perfectly. Rails会完美加载文件。

I'm still pretty noob and I'm not sure why this works but it works. 我仍然还是个菜鸟,不知道为什么能行,但是行得通。 If someone would like to explain it to me I'd appreciate it :DI hope this helps someone either way. 如果有人想向我解释它,我将不胜感激:DI希望这对任何人都可以有所帮助。

I had the same problem. 我有同样的问题。 Here is how I solved it. 这是我解决的方法。 The solution loads the lib directory and all the subdirectories (not only the direct). 该解决方案将加载lib目录和所有子目录(不仅是直接目录)。 Of course you can use this for all directories. 当然,您可以将其用于所有目录。

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

config.autoload_paths does not work for me. config.autoload_paths对我不起作用。 I solve it in other way 我用其他方式解决

Ruby on rails 3 do not automatic reload (autoload) code from /lib folder. Ruby on Rails 3不会从/ lib文件夹自动重新加载(自动加载)代码。 I solve it by putting inside ApplicationController 我通过放入ApplicationController解决它

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

If only certain files need access to the modules in lib, just add a require statement to the files that need it. 如果只有某些文件需要访问lib中的模块,则只需在需要文件的文件中添加一条require语句即可。 For example, if one model needs to access one module, add: 例如,如果一个模型需要访问一个模块,请添加:

require 'mymodule'

at the top of the model.rb file. 在model.rb文件的顶部。

As of Rails 5 , it is recommended to put the lib folder under app directory or instead create other meaningful name spaces for the folder as services , presenters , features etc and put it under app directory for auto loading by rails. Rails 5 ,建议将lib文件夹放置在app目录下,或者为该文件夹创建其他有意义的名称空间,如servicespresentersfeatures等,并将其放置在app目录下以供Rails自动加载。

Please check this GitHub Discussion Link as well. 请同时查看此GitHub讨论链接

There are several reasons you could have problems loading from lib - see here for details - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/ 有几种原因可能会导致您从lib加载时遇到问题-有关详细信息,请参见此处-http: //www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • fix autoload path 修复自动加载路径
  • threadsafe related 线程安全相关
  • naming relating 命名相关
  • ... ...

Spell the filename correctly. 正确拼写文件名。

Seriously. 说真的 I battled with a class for an hour because the class was Governance::ArchitectureBoard and the file was in lib/governance/architecture_baord.rb (transposed O and A in "board") 我与一个班级竞争了一个小时,因为该班级是Governance :: ArchitectureBoard,并且文件位于lib / governance / architecture_baord.rb中(“ board”中的O和A换位了)

Seems obvious in retrospect, but it was the devil tracking that down. 回想起来似乎很明显,但这是魔鬼的追踪。 If the class is not defined in the file that Rails expects it to be in based on munging the class name, it is simply not going to find it. 如果该类未在Rails希望基于修改类名的文件中定义,则根本不会找到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM