Having some trouble working out the migration from Classic to Zeitwerk.
After enabling zeitwerk and running rails s
, everything seems to work. Then after saving a .rb file and refreshing, I'm seeing an "uninitialized constant" error when trying to require a file from the top level /lib
.
Something is misconfigured w/ reloading, but I'm scratching my head trying to work out the details. I was under the impression that having a top level /lib
folder is fine and using require
to load files in that directory is compatible with Zeitwerk, but now I'm not so sure... ideas as to what I'm getting wrong?
Note: I'm not currently setting any specific eager_load_paths
or autoload_paths
EDIT: updated with logging output as suggested by @Xavier
[email protected]: module CustomModule autovivified from directory *********/app/workers/custom_module
[email protected]: autoload set for CustomModule::Profiler, to be loaded from *********/app/workers/custom_module/profiler.rb
[email protected]: autoload set for CustomModule::AnotherProfiler, to be loaded from *********/app/workers/custom_module/another_profiler.rb
NameError - uninitialized constant CustomModule::AttributeParser
Did you mean? NameParserConstants:
app/models/user.rb:180:in `first_name'
app/middleware/catch_json_parse_errors.rb:8:in `call'
app/middleware/decompress_requests.rb:22:in `call'
The namespace
CustomModule
is shared in parts of the project that are reloadable (underapp
), and also in parts where is not (underlib
).This is fine, it is supported. You only need to deliberately think about load priorities, because if
lib
definesCustomModule::Foo
and Rails believesCustomModule
is reloadable, on reload nobody is loadingCustomModule::Foo
again, andrequire
is idempotent, soCustomModule::Foo
won't be found anymore.The solution is to make sure
lib
defines the namespace, and Rails autoloaders reopen it. Essentially same as documented here. This can be done by issuing arequire
in an initializer that loads the namespace fromlib
, for example.That way, when the autoloader scans the file system, it knows it is not responsible for managing
CustomModule
. It will descend. If there are child constants there everything will work as usual, and those constants will be reloaded, but the namespace itself won't.