From dd96e8e3337c04c5c37ece7983d012a9353804ac Mon Sep 17 00:00:00 2001 From: Genadi Samokovarov Date: Tue, 9 Dec 2014 12:04:50 +0200 Subject: [PATCH] Add class level case operator support for error dispatching in Rescuable --- activesupport/CHANGELOG.md | 16 ++++++++++ activesupport/lib/active_support/rescuable.rb | 4 +-- activesupport/test/rescuable_test.rb | 29 +++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 912b0287af..3f340958ea 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,19 @@ +* Added support for error dispatcher classes in ActiveSupport::Rescuable. Now it acts closer to Ruby's rescue. + + class BaseController < ApplicationController + module ErrorDispatcher + def self.===(other) + Exception === other && other.respond_to?(:status) + end + end + + rescue_from ErrorDispatcher do |error| + render status: error.status, json: { error: error.to_s } + end + end + + *Genadi Samokovarov* + * Added `#verified` and `#valid_message?` methods to `ActiveSupport::MessageVerifier` Previously, the only way to decode a message with `ActiveSupport::MessageVerifier` was to use `#verify`, which would raise an exception on invalid messages. Now `#verified` can also be used, which returns `nil` on messages that cannot be decoded. diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb index a7eba91ac5..1a02acd5b1 100644 --- a/activesupport/lib/active_support/rescuable.rb +++ b/activesupport/lib/active_support/rescuable.rb @@ -60,7 +60,7 @@ module ActiveSupport end klasses.each do |klass| - key = if klass.is_a?(Class) && klass <= Exception + key = if klass.is_a?(Module) && klass.respond_to?(:===) klass.name elsif klass.is_a?(String) klass @@ -101,7 +101,7 @@ module ActiveSupport # itself when rescue_from CONSTANT is executed. klass = self.class.const_get(klass_name) rescue nil klass ||= klass_name.constantize rescue nil - exception.is_a?(klass) if klass + klass === exception if klass end case rescuer diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb index b8af888f7c..bd43ad0797 100644 --- a/activesupport/test/rescuable_test.rb +++ b/activesupport/test/rescuable_test.rb @@ -12,6 +12,12 @@ end class CoolError < StandardError end +module WeirdError + def self.===(other) + Exception === other && other.respond_to?(:weird?) + end +end + class Stargate attr_accessor :result @@ -29,6 +35,10 @@ class Stargate @result = e.message end + rescue_from WeirdError do + @result = 'weird' + end + def dispatch(method) send(method) rescue Exception => e @@ -47,6 +57,16 @@ class Stargate raise MadRonon.new("dex") end + def weird + StandardError.new.tap do |exc| + def exc.weird? + true + end + + raise exc + end + end + def sos @result = 'killed' end @@ -91,14 +111,19 @@ class RescuableTest < ActiveSupport::TestCase assert_equal 'dex', @stargate.result end + def test_rescue_from_error_dispatchers_with_case_operator + @stargate.dispatch :weird + assert_equal 'weird', @stargate.result + end + def test_rescues_defined_later_are_added_at_end_of_the_rescue_handlers_array - expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon"] + expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError"] result = @stargate.send(:rescue_handlers).collect(&:first) assert_equal expected, result end def test_children_should_inherit_rescue_definitions_from_parents_and_child_rescue_should_be_appended - expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "CoolError"] + expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError", "CoolError"] result = @cool_stargate.send(:rescue_handlers).collect(&:first) assert_equal expected, result end