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:
Well, after some digging, it actually is really simple. Just need to run the following.
Rails.application.eager_load!
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!
With Rails 6, Zetiwerk became the default code loader.
Try this for eager loading:
Zeitwerk::Loader.eager_load_all
From Configuring Rails Applications
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