Skip to content

Instantly share code, notes, and snippets.

@joshleaves
Created May 15, 2015 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshleaves/10de348b0e8b28863213 to your computer and use it in GitHub Desktop.
Save joshleaves/10de348b0e8b28863213 to your computer and use it in GitHub Desktop.
Thought of a rails feature and about to submit it. I can haz feedback?
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 3b905b1..2bc0653 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,28 @@
+* Exceptions classes responding to `#to_proc` can be passed to `rescue_from` in
+ controllers without an handler. Exceptions can be extended to reply by themselves
+ to errors.
+
+ class JediError < StandardError
+ def to_proc
+ Proc.new do |e|
+ redirect_to :root, notice: "Error: #{e.message}"
+ end
+ end
+ end
+
+ class DroidsController < ApplicationController
+ rescue_from MyError
+
+ def index
+ raise JediError.new("These are not the droids you're looking for.")
+ end
+ end
+
+ I know of no exceptions classes that respond to `#to_proc` so breaking existing APIs
+ shouldn't be a concern.
+
+ *Arnaud Rouyer*
+
* Add Integer#positive? and Integer#negative? query methods in the vein of Fixnum#zero?
This makes it nicer to do things like bunch_of_numbers.select(&:positive?).
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index fcf5553..739cbda 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -55,7 +55,11 @@ module ActiveSupport
if block_given?
options[:with] = block
else
- raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument."
+ unless klasses.select do |klass|
+ klass.is_a?(Module) && klass.method_defined?(:to_proc)
+ end.length == klasses.length
+ raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument."
+ end
end
end
@@ -104,6 +108,7 @@ module ActiveSupport
klass === exception if klass
end
+ rescuer = exception.to_proc if rescuer.is_a?(NilClass) && exception.respond_to?(:to_proc)
case rescuer
when Symbol
method(rescuer)
diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb
index bd43ad0..2ef2001 100644
--- a/activesupport/test/rescuable_test.rb
+++ b/activesupport/test/rescuable_test.rb
@@ -18,6 +18,14 @@ module WeirdError
end
end
+class AsgardError < StandardError
+ def to_proc
+ Proc.new do |e|
+ @result = e.message
+ end
+ end
+end
+
class Stargate
attr_accessor :result
@@ -39,6 +47,8 @@ class Stargate
@result = 'weird'
end
+ rescue_from AsgardError
+
def dispatch(method)
send(method)
rescue Exception => e
@@ -67,6 +77,10 @@ class Stargate
end
end
+ def call_asgard
+ raise AsgardError.new("asgard?")
+ end
+
def sos
@result = 'killed'
end
@@ -116,14 +130,19 @@ class RescuableTest < ActiveSupport::TestCase
assert_equal 'weird', @stargate.result
end
+ def test_rescue_from_with_self_replying_exception
+ @stargate.dispatch :call_asgard
+ assert_equal 'asgard?', @stargate.result
+ end
+
def test_rescues_defined_later_are_added_at_end_of_the_rescue_handlers_array
- expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError"]
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError", "AsgardError"]
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", "WeirdError", "CoolError"]
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError", "AsgardError", "CoolError"]
result = @cool_stargate.send(:rescue_handlers).collect(&:first)
assert_equal expected, result
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment