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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3356742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:58:30  来源:igfitidea点击:

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

ruby-on-railsclassmoduleautoloadruby-on-rails-3

提问by Vincent

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);
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);

采纳答案by Slobodan Kovacevic

As of Rails 2.3.9, there is a setting in config/application.rbin 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)

回答by thankful

# 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. If you want the comfort to autoreload those files, read: Rails 3 Quicktip: Auto reload lib folders in development mode. Be aware that this is not meant for a production environment since the permanent reload slows down the machine.

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

回答by Timo

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. 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.rbsomething like:

因此,当涉及从子目录加载内容时,您应该注意一些问题或约定。有时 Ruby/Rails 的魔力(这次主要是 Rails)会让人难以理解为什么会发生某些事情。任何在自动加载路径中声明的模块只有在模块名称对应于父目录名称时才会加载。因此,如果您尝试输入以下内容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 foothus hosting your module at path: 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. 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.rband lib/my_stuff/foo.rband the former being the same as above and the latter containing a single line: require "bar"and that would work just the same.

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

P.S. 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. 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. 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. :)

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



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. You don't need Rails to do 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. 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. 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.

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

回答by u445908

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. 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! whatever the target class is a new class or an "open class" or "monkey patch" for existing class, it always works!

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

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

For more details , see: https://stackoverflow.com/a/6797707/445908

更多详情,请参见:https: //stackoverflow.com/a/6797707/445908

回答by Brian Armstrong

Very similar, but I think this is a little more elegant:

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

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

回答by Nick Res

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 :D I hope this helps someone either way.

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

回答by hjuskewycz

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). Of course you can use this for all directories.

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

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

回答by msa.im

config.autoload_paths does not work for me. I solve it in other way

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

Ruby on rails 3 do not automatic reload (autoload) code from /lib folder. I solve it by putting inside ApplicationController

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

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

回答by Mike Fischer

If only certain files need access to the modules in lib, just add a require statement to the files that need it. For example, if one model needs to access one module, add:

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

require 'mymodule'

at the top of the model.rb file.

在 model.rb 文件的顶部。

回答by Ashik Salman

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, featuresetc and put it under app directory for auto loading by rails.

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

Please check this GitHub Discussion Linkas well.

请同时查看此GitHub 讨论链接