In a larger project, I am catching specific exceptions, adding some details to the message and then re-raising the same exception. Here is the basic idea of what I'm doing.
#!/usr/bin/env ruby
begin
puts 12 / 0
rescue ZeroDivisionError => e
raise e.exception("new message #{e.message}")
end
When I execute temp.rb from the command line, two exceptions are printed:
% ./temp.rb
./temp.rb:4:in `/': new message divided by 0 (ZeroDivisionError)
from ./temp.rb:4:in `<main>'
./temp.rb:4:in `/': divided by 0 (ZeroDivisionError)
from ./temp.rb:4:in `<main>'
I'm assuming that there is a stack or a list of exceptions somewhere and the exit process of Ruby prints out the entire list or stack of exceptions. I can see great benefits to this. But in my case, I'd like to get rid of the original exception from the list or stack. Is there a way to do this?
CodePudding user response:
The "second" (original) exception is the cause
of the rescued exception which is references by your new exception as it is created with Exception#exception
.
Starting with Ruby 3.1, irb
prints the details of the cause in addition to the actual exception to aid in debugging. Previous Ruby versions have ignored the cause
here.
Thus, you can use other means to handle your exceptions rather than using Ruby's default handler of printing the details of an otherwise unhandled exception, e.g. by adding an explicit exception handler. Alternatively, you can also explicitly set the cause
as you are creating your new exception:
begin
puts 12 / 0
rescue ZeroDivisionError => e
raise e.class, "new message #{e.message}", cause: nil
end
CodePudding user response:
May be something like this to extend Exception
with custom method
Exception.class_eval do
def add_message(msg)
mod =
Module.new do
define_method :to_s do
"#{super()} #{msg}"
end
end
extend mod
end
end
And then
begin
puts 12 / 0
rescue ZeroDivisionError => e
raise e.add_message("(even don't try it)")
end