Get a Backtrace for Debugging Without Throwing an Exception
In one of my current projects, I ran into a very annoying situation where an object attribute was getting set to an incorrect value. The problem was that I didn’t know where this was happening. Furthermore, as far as I could tell, it was being set in a method that had a complex series of alias_method_chains and callbacks. After spending far too long debugging what turned out to be a simple issue, I realized I needed a better solution for the future.
What I really wanted was a backtrace showing what method chain had led to setting the attribute incorrectly. However, as far as I could tell, there was no easy way to get a backtrace outside of raising an Exception. So I came up with a little helper to make this process easier:
class Object
def backtrace
raise
rescue Exception => e
e.backtrace[1..-1] # Leave off first line since we don't care about it
end
endAs you can see, nothing complex is going on here. We’ve added a new method to the Object class, which means that it’s available to all other classes. We raise an error, immediately capture it and return its backtrace. We cut off the first line of the backtrace since it’s only a reference to the backtrace method itself which we’re not too interested. (And yes, I know this means the title is a bit of a lie since an exception is thrown in our backtrace method, but at least we can avoid it in the main method.)
Here’s a usage example for an ActiveRecord model:
def write_attribute(attr_name, value)
logger.info "write_attribute backtrace\n#{backtrace.join("\n")}"
super
endOutput will look like a normal backtrace, but without the clutter of raising an Exception.