Rails force models to eager load
Well, after some digging, it actually is really simple. Just need to run the following.
Rails.application.eager_load!
From Configuring Rails Applications
- config.eager_load when true Eager loads all registeredconfig.eager_load_namespaces. This includes your application,engines, Rails frameworks and any other registered namespace.
- config.eager_load_namespaces registers namespaces that are eagerloaded when config.eager_load is true. All namespaces in the listmust respond to the eager_load! method.
- config.eager_load_paths accepts an array of paths from which Railswill eager load on boot if cache classes is enabled. Defaults toevery folder in the app directory of the application.
EDIT:
To manually load you should be able to do something like:
matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require_dependency file.sub(matcher, '\1')end
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!)
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.
Behind the scenes
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
These directories are not currently included in a default Rails.application.eager_load!