From f48bb1b4ad86bad71ae9c3e5dd3db6b4cb80e4d1 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 17 Nov 2016 14:49:07 -0500 Subject: [PATCH] Call fallback exception handlers with the right exception The issue presented in #26246 showed a deeper underlying problem. When we fell back to the exception handler for an exceptions cause, we were calling that handler with the outer raised exception. This breaks the calling code's expectations, especially if the exception has methods on it behond those from `StandardError`. --- activesupport/lib/active_support/rescuable.rb | 13 ++++++++++--- activesupport/test/rescuable_test.rb | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb index 135690cc42..7f29c955f9 100644 --- a/activesupport/lib/active_support/rescuable.rb +++ b/activesupport/lib/active_support/rescuable.rb @@ -85,14 +85,16 @@ module ActiveSupport # # Returns the exception if it was handled and +nil+ if it was not. def rescue_with_handler(exception, object: self) - if handler = handler_for_rescue(exception, object: object) + handler, exception = handler_for_rescue(exception, object: object) + if handler handler.call exception exception end end def handler_for_rescue(exception, object: self) #:nodoc: - case rescuer = find_rescue_handler(exception) + rescuer, exception = find_rescue_handler(exception) + result = case rescuer when Symbol method = object.method(rescuer) if method.arity == 0 @@ -107,6 +109,7 @@ module ActiveSupport -> e { object.instance_exec(e, &rescuer) } end end + [result, exception] end private @@ -121,7 +124,11 @@ module ActiveSupport end end - handler || find_rescue_handler(exception.cause) + if handler + [handler, exception] + else + find_rescue_handler(exception.cause) + end end end diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb index 7e5c3d1a8f..f7eb047d44 100644 --- a/activesupport/test/rescuable_test.rb +++ b/activesupport/test/rescuable_test.rb @@ -137,6 +137,6 @@ class RescuableTest < ActiveSupport::TestCase def test_rescue_falls_back_to_exception_cause @stargate.dispatch :fall_back_to_cause - assert_equal "unhandled RuntimeError with a handleable cause", @stargate.result + assert_equal "dex", @stargate.result end end