Rails 强制模型快速加载 [英] Rails force models to eager load
问题描述
我希望能够加载整个应用程序,以便我可以找到给定类的后代.
I would like to be able to load an entire app so that I may find the descendants of a given class.
例如,我定义了以下类:
For example given I have the following class defined:
# app/models/foo_class.rb
class FooClass < MySpecialBaseClass
# pasta code
end
它不会被找到:
irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass }
=> []
直到我调用常量:
irb> FooClass
然后返回:
irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass }
=> [FooClass]
我该怎么做?
推荐答案
经过大量的反复试验,我最近了解到 Jason Waldrip 的回答有些不完整.从 Rails 5 开始,Rails.application.eager_load!
确实会加载 config/application.rb
中指定的所有目录.但它与 Rails 在生产中的实际行为不符.要做到这一点,你必须镜像 Rails 所做的:
After a great deal of trial and error, I recently learned that Jason Waldrip's answer is somewhat incomplete. As of Rails 5, Rails.application.eager_load!
will indeed load all of the directories specified in config/application.rb
. But it doesn't match Rails' actual behavior in production. To do that, one must instead mirror what Rails does:
Rails.configuration.eager_load_namespaces.each(&:eager_load!)
这两种方法之间的显着区别在于,OP 不会急切加载位于 gems
或 vendor 中的
文件夹.而 Rails 本身将识别 Engine
的应用程序目录中的文件Engine
的子类存在的位置,并确保适当的 app
子目录被预先加载.
The salient difference between the approaches is that OPs answer won't eager load the files within app directories of Engine
s that live in the gems
or vendor
folders. Whereas Rails itself will identify where subclasses of Engine
exist and will see to it that the appropriate app
subdirectories are eager-loaded.
幕后
Rails 5 在 railties-5.0.2/lib/rails/engine/configuration.rb:39
中添加了预先加载目录,它运行的地方
Rails 5 adds eager load directories in railties-5.0.2/lib/rails/engine/configuration.rb:39
, where it runs
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!
These directories are not currently included in a default Rails.application.eager_load!
这篇关于Rails 强制模型快速加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!