1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow a fallback value to be returned from Rails.error.handle

This commit is contained in:
Kevin McPhillips 2021-11-24 11:19:00 -05:00
parent 89b1cc4818
commit ac751edab3
No known key found for this signature in database
GPG key ID: 2D9D8C7229C91AA1
2 changed files with 47 additions and 9 deletions

View file

@ -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: {})

View file

@ -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)