Rails: When an Uninitialized Constant Hits the Vent
Last two weeks I was seeing the production server of one of my clients hit the same error over and over with no visible pattern. This second it works, the next it fails and leaves the Mongrel cluster in an undefined state somewhere between this world and hell.
The error I’m referring to is:
... backtrace follows ...
I need to repeat that it comes and goes under some non-obvious circumstances, and is hard to recreate. Fortunately, I found the solution and here’s what it was.
I have a directory hierarchy like below. I’m sure when you see it, it all becomes obvious and simple, but it wasn’t for me at that time as there were many files that I omitted below.
/my_module
klass1.rb
...
utils.rb
/utils
net_session.rb
The piece of code in klass1 that failed looks as follows:
Utils::NetSession.new
end
Simple, heh.
Utils.rb is a helper module which is included into MyModule, but apparently loaded only when really necessary (it’s the only explanation why it didn’t fail all the time, as you will see). When it is loaded and included, the MyModule::Utils becomes defined, and Utils::NetSession resolution starts to fail. It happens as Rails begins looking for Utils name space from MyModule, finds MyModule::Utils and doesn’t find any NetSession there. That’s pretty much all to it.
The solutions are:
- Either rename utils.rb (which I did in favor of utilities.rb), or
- Use “::Utils::NetSession.new” (which is not safe as one day you can forget about the leading “::”, and get back to roots)
Hope this helps someone like me fighting the way through these extremely infrequent but painful Rails gotchas.
March 24th, 2008 at 10:13
Hi, Alexey!
As I can see you’ve faced with RoR much later than with Java, so the Grails framewok could be interesting for you because it has RoR ideology, and you can stil use your Java code with it.
March 24th, 2008 at 10:38
Correct. I tried to start with Grails / Groovy several times, but each time it looked more like a kludge to me or an effort to reproduce what Rails already has. It looks like the developers who are bound to use Java in their organizations look for the way to make it as Rails as possible.
Personally, I don’t see any reason to step on my throat and force myself into using these frameworks if I can do Rails. I mean, why? Just to be on the Java side or because I spent more than 7 years programming on it? I’m not bound by corporate obligations and regulations, and I choose whatever works best for me and aids my freelancing business — that’s the essence of being pragmatic programmer, by the way.
I don’t value my past achievements as much as I do the opportunities. If new approaches and technologies overpass the past, it makes it even better and far more fun.
Downloading your presentation on Grails now to see your position better…
Thanks for the comment!
June 11th, 2008 at 03:46
Thanks, I had a similar problem.
I often need to specify the root class (leading ‘::’ thing), so I’m happy with that. But, a couple of my controllers had the leading ‘::’ specified in my routes file. There was no good reason for this, it didn’t cause any problems on the dev server - but did cause intermittent “unitialized constant” errors on the production server.
The fix was to remove the leading :: in the config/routes.rb file.
Again, I had similar sub-class hierarchies which seem to be conflicting, depending on when things were loaded.