Reputation: 16468
I need to prepend debugging info to all exceptions that occur within a block, but I don't want to mess up the backtrace.$!
doesn't seem to be allowing this in 1.9.3; raise
is replacing the backtrace regardless of what I try.
Ideas?
Here's what I was using originally:
def self.load(filename, virtual_path = nil)
t = Template.new(filename, virtual_path)
t.is_page? ? Page.new(t) : t
rescue
raise $!, "Error loading template '#{filename}'#{virtual_path ? " under virtual path '" + virtual_path + "'" : ""}: #{$!}"
end
The best I've found so far is this:
def self.load(filename, virtual_path = nil)
t = Template.new(filename, virtual_path)
t.is_page? ? Page.new(t) : t
rescue => e
raise e, "Error loading template '#{filename}'#{virtual_path ? " under virtual path '" + virtual_path + "'" : ""}: #{e.message} #{e.backtrace}"
end
This dumps the original stack trace into the message, but still doesn't preserve the old stack trace as the stack trace
Upvotes: 3
Views: 395
Reputation: 46826
If you look at the Kernel#raise method, it can take three parameters:
raise(exception [, string [, array]])
If you want to keep the backtrace, you should specify the array
parameter, which is the callback information.
Example:
Say you originally had:
def some_method()
raise('original message')
end
some_method
#=> scratch.rb:10:in `some_method': original message (RuntimeError)
# from scratch.rb:16:in `<main>'
You can use the third parameter of the exception to raise a new exception with updated message and the same backtrace:
def some_method()
begin
raise('error message')
rescue
raise $!, 'new message', $!.backtrace
end
end
some_method
#=> scratch.rb:10:in `some_method': new message (RuntimeError)
# from scratch.rb:16:in `<main>'
As you can see, the new exception is the same as the original exception, except with the updated message.
Upvotes: 4