29

我希望能够加载整个应用程序,以便我可以找到给定类的后代。

例如,给定我定义了以下类:

# app/models/foo_class.rb
class FooClass < MySpecialBaseClass
  # pasta code
end

它不会被发现:

irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass }
=> []

直到我调用 const:

irb> FooClass

然后返回:

irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass } 

=> [FooClass]

我该怎么做呢?

4

4 回答 4

39

好吧,经过一番挖掘,它实际上非常简单。只需要运行以下。

Rails.application.eager_load!
于 2013-11-12T06:48:34.483 回答
10

经过大量的反复试验,我最近了解到 Jason Waldrip 的答案有些不完整。从 Rails 5 开始,Rails.application.eager_load!确实会加载config/application.rb. 但它与 Rails 在生产中的实际行为不匹配。要做到这一点,必须镜像 Rails 所做的事情:

Rails.configuration.eager_load_namespaces.each(&:eager_load!)

这些方法之间的显着区别在于,OP 的答案不会急切地加载位于or文件夹中的Engines 的应用程序目录中的文件。而 Rails 本身识别子类的存在位置,并确保适当的子目录被预先加载。gemsvendorEngineapp

在幕后

railties-5.0.2/lib/rails/engine/configuration.rb:39Rails 5在它运行的地方添加了急切加载目录

      paths.add "app",                 eager_load: true, glob: "{*,*/concerns}"
      paths.add "app/assets",          glob: "*"
      paths.add "app/controllers",     eager_load: true
      paths.add "app/channels",        eager_load: true, glob: "**/*_channel.rb"
      paths.add "app/helpers",         eager_load: true
      paths.add "app/models",          eager_load: true
      paths.add "app/mailers",         eager_load: true

这些目录当前不包含在默认值中Rails.application.eager_load!

于 2018-07-26T02:59:37.490 回答
9

配置 Rails 应用程序

  1. config.eager_load 当为真时 Eager 加载所有注册的 config.eager_load_namespaces。这包括您的应用程序、引擎、Rails 框架和任何其他已注册的命名空间。
  2. config.eager_load_namespaces 注册在 config.eager_load 为 true 时预先加载的命名空间。列表中的所有命名空间都必须响应 eager_load!方法。
  3. config.eager_load_paths 接受一个路径数组,如果启用了缓存类,Rails 将在启动时从这些路径中进行预加载。默认为应用程序的 app 目录中的每个文件夹。

编辑:

要手动加载,您应该能够执行以下操作:

matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
  require_dependency file.sub(matcher, '\1')
end
于 2013-11-11T18:20:39.420 回答
8

Rails 6中,Zeitwerk成为了默认的代码加载器。

尝试以下方法进行预加载:

Zeitwerk::Loader.eager_load_all
于 2019-10-08T16:50:26.067 回答