Ruby-on-rails 将 lib 添加到 Rails 3 中的“config.autoload_paths”不会自动加载我的模块

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4074830/
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 23:31:48  来源:igfitidea点击:

Adding lib to 'config.autoload_paths' in Rails 3 does not autoload my module

ruby-on-rails

提问by Ph??ng Nguy?n

I place a file name g.rb in side Rails.root/libfolder The file content is like this:

我在侧Rails.root/lib文件夹中放置了一个文件名 g.rb文件内容是这样的:

module Google
end

Then I add

然后我添加

config.autoload_paths += %W(#{config.root}/lib #{Rails.root}/app/delayed_jobs)

to my Rails.root/config/application.rb

给我的 Rails.root/config/application.rb

However, when I try to invoke Google from rails console, an exception is thrown. The exception goes away only if I execute require 'google'. Why? Shouldn't my file is autoloaded and shouldn't I access the module without any extra requirestatement?

但是,当我尝试从 调用 Google 时rails console,会引发异常。只有当我执行时异常才会消失require 'google'。为什么?我的文件不应该自动加载require吗,我不应该在没有任何额外声明的情况下访问模块吗?

回答by Ph??ng Nguy?n

Hmm, I discovered an interesting thing. In order for Rails to auto load my class, the class name should be compliant to the file name and the folder structure. For example, if I want to have Google module autoloaded, I must placed it inside google.rb, directly under /lib (incase I specify autoload from /lib). If I want to auto load Google::Docs, then I either place it inside google.rbor google/docs.rb

嗯,我发现了一个有趣的事情。为了让 Rails 自动加载我的类,类名应该符合文件名和文件夹结构。例如,如果我想让 Google 模块自动加载,我必须将它放在 里面google.rb,直接放在 /lib 下(如果我指定从 /lib 自动加载)。如果我想自动加载Google::Docs,那么我要么把它放在里面,google.rb要么google/docs.rb

回答by Don Leatham

I had a similar problem with getting my module to run on Heroku. In addition to the autoload naming convention stated by Stephen C, I found out that the module code must be require'd due to a threadsafeassumption made by the Rails' production environment on Heroku (even though threadsafewas commented out in my production.rbconfiguration file.) As soon as I require'd the module file before calling includeon the module, everything started to work.

我在让我的模块在 Heroku 上运行时遇到了类似的问题。除了 Stephen C 声明的自动加载命名约定之外,我发现模块代码必须是由 Heroku 上的 Rails 生产环境做出requirethreadsafe假设(即使threadsafe在我的production.rb配置文件中被注释掉。)正如我require在调用模块之前调用模块文件一样include,一切都开始工作了。

require 'mymodule'
include Mymodule

Please take a look at this excellent articleon the subject of getting Modules to load correctly in Heroku (production).

请查看这篇关于在 Heroku(生产)中正确加载模块的主题的优秀文章

回答by Stephen C

That's because the point of autoload is notto 'require' everything up front (startup penalty). Classes are loaded as they are needed/referenced. In order to do this, you need some way to know where to look for the class. Otherwise, you would have to load every file in the autoload directory in advance to see what classes are declared. It's a tradeoff, but requiring everything in advance (as marbaq suggests) is not autoloading. You can use the autoload command as provided by Ruby, which takes two arguments, the module to load (symbolized, i.e. :Google in your case), and the second argument is the filename, which would be g.rb if lib is in your load path ($:). See the Ruby docs for autoload.

这是因为自动加载的重点不是预先“要求”所有内容(启动惩罚)。类在需要/引用时加载。为了做到这一点,您需要某种方式来知道在哪里查找类。否则,您必须提前加载自动加载目录中的每个文件以查看声明了哪些类。这是一种权衡,但要求一切提前(如 marbaq 所建议的)并不是自动加载。您可以使用 Ruby 提供的 autoload 命令,它需要两个参数,要加载的模块(符号化,即:Google 在您的情况下),第二个参数是文件名,如果 lib 在您的加载路径 ($:)。有关自动加载,请参阅 Ruby 文档。

回答by E. Sambo

Change config.autoload_pathsto config.eager_load_paths

更改config.autoload_pathsconfig.eager_load_paths

(based on Rails issue #6850and Force reload! from lib directory in rails 3.2 console)

(基于Rails 问题 #6850Force reload! from lib directory in rails 3.2 console

回答by Fredrik Bostr?m

I faced the same problem just now, and my "solution" (or rather workaround) was to manually require every needed file from Rails.root/lib in my application.rb.

我刚才遇到了同样的问题,我的“解决方案”(或者更确切地说是解决方法)是在我的 application.rb 中手动要求 Rails.root/lib 中的每个需要的文件。

require 'lib/message'
require 'lib/store'
require 'lib/vault/vault.rb'
require 'lib/custom_loggers'

module MyApplication
  class Application < Rails::Application

My next step would be to categorize the files in module folders as you mention.

我的下一步是对您提到的模块文件夹中的文件进行分类。

回答by ben.m

i found this solution recently

我最近找到了这个解决方案

config/application.rb

配置/应用程序.rb

module AppName
  class Application < Rails::Application

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
    config.autoload_paths += Dir[Rails.root.join('app', 'lib', 'extensions')] 

  end
end

the first config call induces rails to auto-load all sub-directories of the app/models directory so now i can have /app/models/sub_directory/model.rb auto-loaded (handy for organising an app with a large code base)

第一个配置调用会导致 rails 自动加载 app/models 目录的所有子目录,所以现在我可以自动加载 /app/models/sub_directory/model.rb (对于组织具有大型代码库的应用程序很方便)

the second config call induces rails to autoload the lib/extensions directory

第二个配置调用导致 rails 自动加载 lib/extensions 目录

hope this helps

希望这可以帮助

note: i believe this is rails 3 specific

注意:我相信这是特定于 Rails 3 的