I recently came across the "need" to attach some user data to an already
existing exception.  My first thought was to create a new exception type
that contained both an exception and user data:

  class Exception_With_Data < Exception
    attr_reader :data

    def initialize(data, exc)
      @data, @exc = data, exc
    end

    def to_s; @exc.to_s; end
    def inspect; @exc.inspect; end
  end

But this is somewhat klunky.  Then it occurred to me that I could just
extend the exception object that I already have:

  module Exception_Data_Mixin
    attr_accessor :data
  end

  begin
    raise 'Foo!'
  rescue RuntimeError
    $!.extend(Exception_Data_Mixin)
    $!.data = 42
    p $!.data           #=> 42
  end

Where I run into problems is if I try to re-raise this exception:

  begin
    begin
      raise 'Foo!'
    rescue RuntimeError
      $!.extend(Exception_Data_Mixin)
      $!.data = 42
      raise $!, $!.message, $!.backtrace
    end
  rescue RuntimeError
    p $!.data           #=> nil
  end

I can re-raise the exception with "raise $!", but then I don't get the
right backtrace:

  begin
    begin
      raise 'Foo!'      # I want the backtrace to point here
    rescue RuntimeError
      $!.extend(Exception_Data_Mixin)
      $!.data = 42
      raise $!          # line 14
    end
  rescue RuntimeError
    p $!.backtrace      #=> ["test.rb:14"]
  end

Is there any way I can re-raise the exception AND get the same backtrace
as the original exception?

Thanks,

Paul