<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>activesupport/test/rescuable_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -41,10 +41,9 @@ module ActionController #:nodoc:
       base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
       base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES
 
-      base.class_inheritable_array :rescue_handlers
-      base.rescue_handlers = []
-
       base.extend(ClassMethods)
+      base.send :include, ActiveSupport::Rescuable
+
       base.class_eval do
         alias_method_chain :perform_action, :rescue
       end
@@ -54,65 +53,12 @@ module ActionController #:nodoc:
       def process_with_exception(request, response, exception) #:nodoc:
         new.process(request, response, :rescue_action, exception)
       end
-
-      # Rescue exceptions raised in controller actions.
-      #
-      # &lt;tt&gt;rescue_from&lt;/tt&gt; receives a series of exception classes or class
-      # names, and a trailing &lt;tt&gt;:with&lt;/tt&gt; option with the name of a method
-      # or a Proc object to be called to handle them. Alternatively a block can
-      # be given.
-      #
-      # Handlers that take one argument will be called with the exception, so
-      # that the exception can be inspected when dealing with it.
-      #
-      # Handlers are inherited. They are searched from right to left, from
-      # bottom to top, and up the hierarchy. The handler of the first class for
-      # which &lt;tt&gt;exception.is_a?(klass)&lt;/tt&gt; holds true is the one invoked, if
-      # any.
-      #
-      #   class ApplicationController &lt; ActionController::Base
-      #     rescue_from User::NotAuthorized, :with =&gt; :deny_access # self defined exception
-      #     rescue_from ActiveRecord::RecordInvalid, :with =&gt; :show_errors
-      #
-      #     rescue_from 'MyAppError::Base' do |exception|
-      #       render :xml =&gt; exception, :status =&gt; 500
-      #     end
-      #
-      #     protected
-      #       def deny_access
-      #         ...
-      #       end
-      #
-      #       def show_errors(exception)
-      #         exception.record.new_record? ? ...
-      #       end
-      #   end
-      def rescue_from(*klasses, &amp;block)
-        options = klasses.extract_options!
-        unless options.has_key?(:with)
-          block_given? ? options[:with] = block : raise(ArgumentError, &quot;Need a handler. Supply an options hash that has a :with key as the last argument.&quot;)
-        end
-
-        klasses.each do |klass|
-          key = if klass.is_a?(Class) &amp;&amp; klass &lt;= Exception
-            klass.name
-          elsif klass.is_a?(String)
-            klass
-          else
-            raise(ArgumentError, &quot;#{klass} is neither an Exception nor a String&quot;)
-          end
-
-          # Order is important, we put the pair at the end. When dealing with an
-          # exception we will follow the documented order going from right to left.
-          rescue_handlers &lt;&lt; [key, options[:with]]
-        end
-      end
     end
 
     protected
       # Exception handler called when the performance of an action raises an exception.
       def rescue_action(exception)
-        rescue_action_with_handler(exception) || rescue_action_without_handler(exception)
+        rescue_with_handler(exception) || rescue_action_without_handler(exception)
       end
 
       # Overwrite to implement custom logging of errors. By default logs as fatal.
@@ -168,18 +114,6 @@ module ActionController #:nodoc:
         render_for_file(rescues_path(&quot;layout&quot;), response_code_for_rescue(exception))
       end
 
-      # Tries to rescue the exception by looking up and calling a registered handler.
-      def rescue_action_with_handler(exception)
-        if handler = handler_for_rescue(exception)
-          if handler.arity != 0
-            handler.call(exception)
-          else
-            handler.call
-          end
-          true # don't rely on the return value of the handler
-        end
-      end
-
       def rescue_action_without_handler(exception)
         log_error(exception) if logger
         erase_results if performed?
@@ -216,36 +150,6 @@ module ActionController #:nodoc:
         rescue_responses[exception.class.name]
       end
 
-      def handler_for_rescue(exception)
-        # We go from right to left because pairs are pushed onto rescue_handlers
-        # as rescue_from declarations are found.
-        _, handler = *rescue_handlers.reverse.detect do |klass_name, handler|
-          # The purpose of allowing strings in rescue_from is to support the
-          # declaration of handler associations for exception classes whose
-          # definition is yet unknown.
-          #
-          # Since this loop needs the constants it would be inconsistent to
-          # assume they should exist at this point. An early raised exception
-          # could trigger some other handler and the array could include
-          # precisely a string whose corresponding constant has not yet been
-          # seen. This is why we are tolerant to unknown constants.
-          #
-          # Note that this tolerance only matters if the exception was given as
-          # a string, otherwise a NameError will be raised by the interpreter
-          # 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
-        end
-
-        case handler
-        when Symbol
-          method(handler)
-        when Proc
-          handler.bind(self)
-        end
-      end
-
       def clean_backtrace(exception)
         if backtrace = exception.backtrace
           if defined?(RAILS_ROOT)</diff>
      <filename>actionpack/lib/action_controller/rescue.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 *Edge*
 
+* Add ActiveSupport::Rescuable module abstracting ActionController::Base rescue_from features. [Norbert Crombach, Pratik]
+
 * Switch from String#chars to String#mb_chars for the unicode proxy.  [Manfred Stienstra]
 
   This helps with 1.8.7 compatibility and also improves performance for some operations by reducing indirection.</diff>
      <filename>activesupport/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -56,6 +56,8 @@ require 'active_support/time_with_zone'
 
 require 'active_support/secure_random'
 
+require 'active_support/rescuable'
+
 I18n.load_path &lt;&lt; File.dirname(__FILE__) + '/active_support/locale/en-US.yml'
 
 Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')</diff>
      <filename>activesupport/lib/active_support.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,28 +1,49 @@
 module ActiveSupport
+  # Rescuable module adds support for easier exception handling.
   module Rescuable
     def self.included(base) # :nodoc:
-      base.class_inheritable_array :rescue_handlers
+      base.class_inheritable_accessor :rescue_handlers
       base.rescue_handlers = []
+
       base.extend(ClassMethods)
     end
 
     module ClassMethods
-      def enable_rescue_for(*methods)
-        methods.each do |method|
-          class_eval &lt;&lt;-EOS
-            def #{method}_with_rescue(*args, &amp;block)
-              #{method}_without_rescue(*args, &amp;block)
-            rescue Exception =&gt; exception
-              rescue_with_handler(exception)
-            end
-
-            alias_method_chain :#{method}, :rescue
-          EOS
-        end
-      end
-
+      # Rescue exceptions raised in controller actions.
+      #
+      # &lt;tt&gt;rescue_from&lt;/tt&gt; receives a series of exception classes or class
+      # names, and a trailing &lt;tt&gt;:with&lt;/tt&gt; option with the name of a method
+      # or a Proc object to be called to handle them. Alternatively a block can
+      # be given.
+      #
+      # Handlers that take one argument will be called with the exception, so
+      # that the exception can be inspected when dealing with it.
+      #
+      # Handlers are inherited. They are searched from right to left, from
+      # bottom to top, and up the hierarchy. The handler of the first class for
+      # which &lt;tt&gt;exception.is_a?(klass)&lt;/tt&gt; holds true is the one invoked, if
+      # any.
+      #
+      #   class ApplicationController &lt; ActionController::Base
+      #     rescue_from User::NotAuthorized, :with =&gt; :deny_access # self defined exception
+      #     rescue_from ActiveRecord::RecordInvalid, :with =&gt; :show_errors
+      #
+      #     rescue_from 'MyAppError::Base' do |exception|
+      #       render :xml =&gt; exception, :status =&gt; 500
+      #     end
+      #
+      #     protected
+      #       def deny_access
+      #         ...
+      #       end
+      #
+      #       def show_errors(exception)
+      #         exception.record.new_record? ? ...
+      #       end
+      #   end
       def rescue_from(*klasses, &amp;block)
         options = klasses.extract_options!
+
         unless options.has_key?(:with)
           if block_given?
             options[:with] = block
@@ -46,18 +67,31 @@ module ActiveSupport
       end
     end
 
+    # Tries to rescue the exception by looking up and calling a registered handler.
     def rescue_with_handler(exception)
       if handler = handler_for_rescue(exception)
         handler.arity != 0 ? handler.call(exception) : handler.call
-      else
-        raise exception
+        true # don't rely on the return value of the handler
       end
     end
 
     def handler_for_rescue(exception)
-      # use reverse so what is added last is found first
-      _, handler = *rescue_handlers.reverse.detect do |klass_name, handler|
-        # allow strings to support constants that are not defined yet
+      # We go from right to left because pairs are pushed onto rescue_handlers
+      # as rescue_from declarations are found.
+      _, handler = Array(rescue_handlers).reverse.detect do |klass_name, handler|
+        # The purpose of allowing strings in rescue_from is to support the
+        # declaration of handler associations for exception classes whose
+        # definition is yet unknown.
+        #
+        # Since this loop needs the constants it would be inconsistent to
+        # assume they should exist at this point. An early raised exception
+        # could trigger some other handler and the array could include
+        # precisely a string whose corresponding constant has not yet been
+        # seen. This is why we are tolerant to unknown constants.
+        #
+        # Note that this tolerance only matters if the exception was given as
+        # a string, otherwise a NameError will be raised by the interpreter
+        # 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</diff>
      <filename>activesupport/lib/active_support/rescuable.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>964dfc15572d7c10771c81ac3cbfb455dd5e378e</id>
    </parent>
  </parents>
  <author>
    <name>Pratik Naik</name>
    <email>pratiknaik@gmail.com</email>
  </author>
  <url>http://github.com/rails/rails/commit/259a7a844b53b7d508145cc61fed9e11581e5409</url>
  <id>259a7a844b53b7d508145cc61fed9e11581e5409</id>
  <committed-date>2008-10-04T14:13:50-07:00</committed-date>
  <authored-date>2008-10-04T13:48:18-07:00</authored-date>
  <message>Add tests for ActiveSupport::Rescuable. Use ActiveSupport::Rescuable in ActionController::Base.</message>
  <tree>ca91608fbab39d03b59137d018046606717883bd</tree>
  <committer>
    <name>Pratik Naik</name>
    <email>pratiknaik@gmail.com</email>
  </committer>
</commit>
