Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show the last-raised error, not its "cause" #459

Merged
merged 1 commit into from Apr 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/better_errors/raised_exception.rb
Expand Up @@ -4,9 +4,8 @@ class RaisedException
attr_reader :exception, :message, :backtrace

def initialize(exception)
if exception.respond_to?(:cause)
exception = exception.cause if exception.cause
elsif exception.respond_to?(:original_exception) && exception.original_exception
if exception.respond_to?(:original_exception) && exception.original_exception
# This supports some specific Rails exceptions, and is not intended to act the same as `#cause`.
exception = exception.original_exception
end

Expand Down
80 changes: 43 additions & 37 deletions spec/better_errors/middleware_spec.rb
Expand Up @@ -93,62 +93,68 @@ module BetterErrors
expect(status).to eq(500)
end

if Exception.new.respond_to?(:cause)
context "cause" do
class OtherException < Exception
def initialize(message)
super(message)
context "when the exception has a cause" do
before do
pending "This Ruby does not support `cause`" unless Exception.new.respond_to?(:cause)
end

let(:app) {
Middleware.new(->env {
begin
raise "First Exception"
rescue
raise "Second Exception"
end
end
})
}

it "shows Original Exception if it responds_to and has an cause" do
app = Middleware.new(->env {
begin
raise "Original Exception"
rescue
raise OtherException.new("Other Exception")
end
})
it "shows the exception as-is" do
status, _, body = app.call({})

status, _, body = app.call({})
expect(status).to eq(500)
expect(body.join).to match(/\n> Second Exception\n/)
expect(body.join).not_to match(/\n> First Exception\n/)
end
end

expect(status).to eq(500)
expect(body.join).not_to match(/\n> Other Exception\n/)
expect(body.join).to match(/\n> Original Exception\n/)
context "when the exception responds to #original_exception" do
class OriginalExceptionException < Exception
attr_reader :original_exception

def initialize(message, original_exception = nil)
super(message)
@original_exception = original_exception
end
end
else
context "original_exception" do
class OriginalExceptionException < Exception
attr_reader :original_exception

def initialize(message, original_exception = nil)
super(message)
@original_exception = original_exception
end
end

it "shows Original Exception if it responds_to and has an original_exception" do
app = Middleware.new(->env {
raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception"))
context 'and has one' do
let(:app) {
Middleware.new(->env {
raise OriginalExceptionException.new("Second Exception", Exception.new("First Exception"))
})
}

it "shows the original exception instead of the last-raised one" do
status, _, body = app.call({})

expect(status).to eq(500)
expect(body.join).not_to match(/Other Exception/)
expect(body.join).to match(/Original Exception/)
expect(body.join).not_to match(/Second Exception/)
expect(body.join).to match(/First Exception/)
end
end

it "won't crash if the exception responds_to but doesn't have an original_exception" do
app = Middleware.new(->env {
raise OriginalExceptionException.new("Other Exception")
context 'and does not have one' do
let(:app) {
Middleware.new(->env {
raise OriginalExceptionException.new("The Exception")
})
}

it "shows the exception as-is" do
status, _, body = app.call({})

expect(status).to eq(500)
expect(body.join).to match(/Other Exception/)
expect(body.join).to match(/The Exception/)
end
end
end
Expand Down