Jacob Fugal <lukfugl / gmail.com> writes:

> On 10/25/05, Yohanes Santoso <ysantoso-rubycore / jenny-gnome.dyndns.org> wrote:
>> Would you accept a patch to provide nested Exception?
>>
>> def remove_user(name)
>>   begin
>>     File.unlink('something')
>>     more_exception_throwing_method_calls
>>   rescue
>>     raise UserManagementFailure.new("unable to remove user #{name}", $!)
>>   end
>> end
>
> Doesn't this already work? Example:
>
>   def example
>     begin
>       raise "Random error"
>     rescue
>       raise "Example failed"
>     end
>   end
>
>   begin
>     example
>   rescue Exception => e
>     puts e
>   end
>
> The output I get is "Example failed".

At this point, you lost the original 'Random error' exception. The
idea is to attach a causing exception to a domain-specific exception
for logging/auditing purposes.

In my example above, the domain-specific exception,
UserManagementFailure would contain the causing exception, say, and
Errno::NOENT exception. This way, when logging exceptions, you can
provide some contextual information:


begin
   ...
   ...
   remove_user('foobar')
rescue UserManagementFailure
   log($!)
rescue ....
end

The logger could extract the causing exception to produce, for example:

Exception: UserManagementFailure: unable to remove user foobar
           ... (some back trace to the "raise UserManagementFailure.new...." here) ...
caused by: Errno::NOENT: no file named 'something' exists
           ... (some back trace to the "File.unlink('something')"... here) ....


So, the patch would add an optional argument to
Exception#initialisation(msg, cause=nil) and Exception.exception(msg,
cause=nil), and a new method: Exception#cause which returns cause.

YS.