Lilith River
Lilith River

Reputation: 16468

Ruby: Prepend info to exception messages without touching stacktrace

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

Answers (1)

Justin Ko
Justin Ko

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

Related Questions