Or, “Man I’m glad Ruby on Rails is an open source framework”.
Ruby on Rails normally provides pretty good debugging information for dealing with errors, but I ran into an odd error today that had no debug info other than the exception itself. Here’s what I did to find and fix the problem.
Symptoms: “So, tell me, how long have you been feeling this way?” I had just added a new controller, model, views, and helpers to my app. Requesting a route to any of the new controller’s actions caused Rails to die with the exception “ActionController::RoutingError (undefined method `sub’ for nil:NilClass)”. No stack trace. No filename / line numbers. I knew one of the 20-odd new files I had just created must be causing the problem, but I didn’t know which one.
Diagnosis: “Breathe in. Breathe again. Again. OK, now cough. Ah, yes, now I see the problem.”: The only way I know of to diagnose these kind of problems is brute force. I added a debugger statement to the top of application_controller.rb and restarted the app. Then I requested a URL that was causing crashes, and from the breakpoint, stepped forward in the debugger (next, next, next…) until the app died. Studying the code that executed just before the app died didn’t yield an obvious result, but about 10 frames up the stack I could see a call to ActiveSupport::Inflector#constantize. I edited that method to print (puts) the parameters it was being called with, then restarted the server and tried again. Voila: the last parameter spit out by #constantize before the server died was the culprit.
#constantize PlaceLinksHelper for name PlaceLinksHelper
The Cure: “Take three of these and call me in the morning.” : It turns out I had created a helper module with the file name “places_helper.rb”, but within that file I mistakenly defined “module PlaceLinksHelper”. For some reason that shall remain a mystery to me, this caused things to fall-down-go-boom. The fix was simply to give the module the name Rails expected to find: “PlacesHelper”.
Upon Reflection… “I sure hope that doesn’t happen to me again. But it probably will.” I don’t know how you do this sort of diagnosis efficiently in a closed-source or compiled environment. This is about the 5th time I’ve edited Rails source code to find and fix an oddball problem. I guess you could try attaching a debugger to binaries and then study the gobbledy-gook, but… no thanks. The only other thing I could have done in a compiled/closed source setup is study each of my own files line by line. That would have worked, but it would have taken far more time.
Source code good.