errors/cause/chain_parens.rb

tests/_examples/errors/cause/chain_parens.rb in the metorex repository.

# `Exception#cause` is the exception a rescue clause was handling when this
# one was raised, nil when there was none, and never the exception itself.

standalone = RuntimeError.new("standalone")
puts(standalone.cause.inspect)

begin
  raise Exception, "the cause"
rescue Exception
  begin
    raise RuntimeError, "the consequence"
  rescue RuntimeError => error
    puts(error.message)
    puts(error.cause.class.to_s)
    puts(error.cause.message)
  end
end

# An error raised inside a rescue body records what it followed, including one
# the interpreter itself raises.
begin
  begin
    1 / 0
  rescue ZeroDivisionError
    raise("followed a division")
  end
rescue RuntimeError => error
  puts(error.cause.class.to_s)
  puts(error.cause.is_a?(ZeroDivisionError).to_s)
  puts(error.cause.is_a?(StandardError).to_s)
end

original = RuntimeError.new("original")
begin
  begin
    raise(original)
  rescue RuntimeError
    1 / 0
  end
rescue ZeroDivisionError => error
  puts(error.cause.equal?(original).to_s)
end

# Re-raising the same exception leaves its cause alone.
begin
  begin
    raise RuntimeError, "re-raised"
  rescue RuntimeError => error
    raise(error)
  end
rescue RuntimeError => error
  puts(error.cause.inspect)
end

# An exception made before the rescue and raised by a method its body calls
# records the exception the rescue was handling.
def raise_from_method(error)
  Kernel.raise(error)
end

begin
  begin
    raise "handled first"
  rescue
    raise(RangeError.new("made in the rescue"))
  end
rescue RangeError => error
  puts(error.cause.inspect)
end

begin
  begin
    raise "handled second"
  rescue
    Kernel.raise(RangeError.new("raised through Kernel"))
  end
rescue RangeError => error
  puts(error.cause.inspect)
end

begin
  begin
    raise "handled first"
  rescue
    raise_from_method(RangeError.new("made earlier"))
  end
rescue RangeError => error
  puts(error.cause.message)
end

Output:

nil
the consequence
Exception
the cause
ZeroDivisionError
true
true
true
nil
#<RuntimeError: handled first>
#<RuntimeError: handled second>
handled first