diff --git a/activesupport/lib/active_support/error_reporter.rb b/activesupport/lib/active_support/error_reporter.rb index b5fcd04332..189ce2ba24 100644 --- a/activesupport/lib/active_support/error_reporter.rb +++ b/activesupport/lib/active_support/error_reporter.rb @@ -19,17 +19,24 @@ module ActiveSupport # # Both methods can be restricted to only handle a specific exception class # - # maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") } + # maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") } # # You can also pass some extra context information that may be used by the error subscribers: # - # Rails.error.handle(context: { section: "admin" }) do - # # ... - # end + # Rails.error.handle(context: { section: "admin" }) do + # # ... + # end # # Additionally a +severity+ can be passed along to communicate how important the error report is. # +severity+ can be one of +:error+, +:warning+ or +:info+. Handled errors default to the +:warning+ # severity, and unhandled ones to +error+. + # + # Both `handle` and `record` pass through the return value from the block. In the special case of `handle` handling an + # error, a fallback value can be provided that will be returned: + # + # user = Rails.error.handle(fallback: User.anonymous) do + # User.find_by(params) + # end class ErrorReporter SEVERITIES = %i(error warning info) @@ -42,15 +49,15 @@ module ActiveSupport # Report any unhandled exception, and swallow it. # - # Rails.error.handle do - # 1 + '1' - # end + # Rails.error.handle do + # 1 + '1' + # end # - def handle(error_class = StandardError, severity: :warning, context: {}) + def handle(error_class = StandardError, severity: :warning, context: {}, fallback: nil) yield rescue error_class => error report(error, handled: true, severity: severity, context: context) - nil + fallback end def record(error_class = StandardError, severity: :error, context: {}) diff --git a/activesupport/test/error_reporter_test.rb b/activesupport/test/error_reporter_test.rb index 300aed8a85..1d1779ec74 100644 --- a/activesupport/test/error_reporter_test.rb +++ b/activesupport/test/error_reporter_test.rb @@ -58,6 +58,30 @@ class ErrorReporterTest < ActiveSupport::TestCase assert_equal [], @subscriber.events end + test "#handle passes through the return value" do + result = @reporter.handle do + 2 + 2 + end + assert_equal 4, result + end + + test "#handle returns nil on handled raise" do + result = @reporter.handle do + raise StandardError + 2 + 2 + end + assert_nil result + end + + test "#handle returns a fallback value on handled raise" do + expected = "four" + result = @reporter.handle(fallback: expected) do + raise StandardError + 2 + 2 + end + assert_equal expected, result + end + test "#record report any unhandled error and re-raise them" do error = ArgumentError.new("Oops") assert_raises ArgumentError do @@ -77,6 +101,13 @@ class ErrorReporterTest < ActiveSupport::TestCase assert_equal [], @subscriber.events end + test "#record passes through the return value" do + result = @reporter.record do + 2 + 2 + end + assert_equal 4, result + end + test "can have multiple subscribers" do second_subscriber = ErrorSubscriber.new @reporter.subscribe(second_subscriber)