A story, in which misaligned module/path names cause Rails to lose track of constants (sometimes) & explicit require statements did SOMETHING strange to the Rails loader.
I wanted to move all user-management code into a namespace called Auth
, to make it mesh neatly with the rest of a “modules within the monolith” structure. (I don’t really remember the details, this was in summer 2019.)
Anyway, I there was a model I forgot to rename in there. Let’s call it UserAction. This model lived in /app/models/auth/user_action.rb
but it was just called UserAction
, not Auth
. There was also a lib/auth/sso_client
helper file that was required at the top of /app/controllers/auth/user_sessions_controller.rb
using require 'auth/sso_client'
.
Rails could find UserAction
just fine. However, it kept on insisting that Auth::UserSessionsController
did not exist. I remember I was co-working with @Noel_Rappin when this first came up, that I had him bullshit-check my work, and that he couldn’t see anything wrong with Auth::UserSessionsController
.
The problem was only happening for me, not for my teammates, and went magically away after a few days.
EXCEPT, a month later, it started happening for everyone intermittently, and also happening in prod.
In order to fix it, I remember needing to:
- rename
UserAction
toAuth::UserAction
- put
lib
under Rails loader control to get rid of therequire 'auth/sso_client'
- remove random other require statements from entirely different parts of the application. (This was particularly annoying because I needed to stop using
require
for some classes that I was using thedef ClassName
constructor pattern for, and Zeitwerk does not autoload those constructors if they are kept in the same file as the method they construct. I was able to work around this but my workaround was hella ugly and confusing.)
I remember trying all of those things in isolation to see if they were actually all required, and they appeared to be. It is however possible that something could have cached itself in a way that makes me incorrect about that. Again, sorry I don’t have better details here.
Since then my team has kept on seeing blips that feel like they’re related. The only concrete one that comes to mind: once, a developer accidentally copypastaed a require 'spec_helper'
to the top of an application code file and similar symptoms emerged. I don’t remember exactly what they were, but they were in the “losing track of classes” genre. If I hadn’t had my past experience and known to search the diff for weird-looking require statements, I imagine that this would have taken me days to debug; the error messages I was seeing would not have pointed me in this direction without that context.
I have tended to attribute these issues to Zeitwerk, because I’ve never seen anything like them before Rails 6. In truth though I have no idea if this is a Zeitwerk thing, a Bootsnap thing, a non-Zeitwerk autoloader thing, some combination of the above…
It’s an ongoing annoyance for me though, and it’s been a day-ruining blocker for other developers on my team.