How rails finds and loads classes when using autoload_paths
and eager_load_paths
can be pretty confusing. This post is the best that I’ve read on the topic, but there are a few things that I think are worth explaining more.
autoload_paths
This helps rails locate where an unknown constant is defined. So if it encounters the constant Foo::Bar::Baz
, it knows to look for it in foo/bar/baz.rb
That is why you only need to add lib/
, instead of lib/**/*
, to the paths. If you had lib/foo/bar
in your autoload path then it would expect Foo::Bar::Baz
to be in lib/foo/bar/foo/bar/baz.rb
. You can check out the current autoload paths using ActiveSupport::Dependencies.autoload_paths
in the rails console.
[4] pry(main)> ActiveSupport::Dependencies.autoload_paths
=> ["<path_to>/app/assets",
"<path_to>/app/controllers",
"<path_to>/app/datatables",
"<path_to>/app/decorators",
...
eager_load_paths
eager_load_paths
are the way to immediately load constants at startup (assuming config.cache_classes
is true
, config.eager_load
actually controls whether eager_load_namespaces
are eager loaded…).
The documentation is somewhat ambiguous as to whether this should be exhaustive like lib/**/*
or whether each path in eager_load_paths
is searched recursively. We can look at the railties source and verify that it does indeed recursively load sub directories of each eager_load_path
.
This is consistent with the behavior described in the above post. Including /lib
will make everything work, but the downside is that things like our rake tasks and other non-web-serving constants will be unnecessarily loaded into memory.
Hope this helps others work through what all rails is doing when you set autoload_paths
or eager_load_paths
.