Autoloading Confusion

Hey all,

Just wanted to share a specific WTF that took more time that I’d like to admit to track down :sweat_smile: and with some help.

I was in the process of moving code from lib/ to app/ and the error was a LoadError unable to autoload constant X error. Only on the first request of server load

No problems with the nesting of modules, naming of files/constants etc.

Took a while to realize that under the app folder rails doesn’t append the module name for searching so instead of app/folder_x, everything needed to be moved to app/lib/folder_x which resolved the problem

A custom error/warning message around this could be helpful.

I’ve seen stuff in a similar genre before – you’re by no means the only one!

Let me understand this one in detail.

Which autoloading mode was this? Did app/folder_x/foo.rb define FolderX::Foo or Foo? Did you have app in the autoload paths? You can check with

rails runner 'pp ActiveSupport::Dependencies.autoload_paths'

Did you move the files to lib or to app/lib (both are mentioned)?

1 Like

I ran into a similar issue last week:

https://stackoverflow.com/questions/61408770/activerecord-bug-with-namespaces-or-expected-behavior

The general consensus in different threads on Stack Overflow seems to be the the Zeitwerk gem (Rails 6) fixes a bunch of the surprises with autoloading in Rails, but that’s not much consolation for those who can’t get to Rails 6 any time soon.

In looking at past Rails issues on GitHub, it’s mentioned that prefixing your namespace with :: should always work, but it doesn’t, unfortunately.

Yes, classic is the only mode it has existed before Rails 6 (classic is a name invented in Rails 6 to distinguish both modes, it did not had a name before).

The technique classic uses has fundamental limitations and there is no way around that. The best we’ve been able to do has been to explain why do these limitations exist, and document them. In your particular case, the problem is that const_missing is called last in the constant lookup algorithms. It is a particular case of When Constants Aren’t Missed. Check that out, it shows you the fix.

Zeitwerk uses a totally different approach that has been possible thanks to changes in recent Ruby versions, and those gotchas are gone. zeitwerk mode matches Ruby semantics and you can use your classes and modules normally without needing to be defensive. The issue in your post doesn’t happen in zeitwerk mode.

If anyone would like to understand which was the limitation of classic, and why zeitwerk is a superior solution, please check this talk from RailsConf 2019.

Zeitwerk has regularly 0 bugs and 0 PRs:

CleanShot 2020-05-08 at 19.31.17@2x

It is a different story, and my hope is that autoloading becomes something discreet and robust you even forget it exists.

6 Likes

I have the same problems. After some time researching i founded problem here - rails/paths.rb at 758e4f8406e680a6cbf21b170749202c537a2576 · rails/rails · GitHub Here, are used “glob” with sorting.