|
f8dbd416
»
|
jeremy |
2009-03-24 |
Explicit dependency on clas... |
1 |
require 'active_support/core_ext/class/inheritable_attributes' |
| |
2 |
|
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
3 |
module ActiveSupport |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
4 |
# Rescuable module adds support for easier exception handling. |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
5 |
module Rescuable |
| |
6 |
def self.included(base) # :nodoc: |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
7 |
base.class_inheritable_accessor :rescue_handlers |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
8 |
base.rescue_handlers = [] |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
9 |
|
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
10 |
base.extend(ClassMethods) |
| |
11 |
end |
| |
12 |
|
| |
13 |
module ClassMethods |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
14 |
# Rescue exceptions raised in controller actions. |
| |
15 |
# |
| |
16 |
# <tt>rescue_from</tt> receives a series of exception classes or class |
| |
17 |
# names, and a trailing <tt>:with</tt> option with the name of a method |
| |
18 |
# or a Proc object to be called to handle them. Alternatively a block can |
| |
19 |
# be given. |
| |
20 |
# |
| |
21 |
# Handlers that take one argument will be called with the exception, so |
| |
22 |
# that the exception can be inspected when dealing with it. |
| |
23 |
# |
| |
24 |
# Handlers are inherited. They are searched from right to left, from |
| |
25 |
# bottom to top, and up the hierarchy. The handler of the first class for |
| |
26 |
# which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if |
| |
27 |
# any. |
| |
28 |
# |
| |
29 |
# class ApplicationController < ActionController::Base |
| |
30 |
# rescue_from User::NotAuthorized, :with => :deny_access # self defined exception |
| |
31 |
# rescue_from ActiveRecord::RecordInvalid, :with => :show_errors |
| |
32 |
# |
| |
33 |
# rescue_from 'MyAppError::Base' do |exception| |
| |
34 |
# render :xml => exception, :status => 500 |
| |
35 |
# end |
| |
36 |
# |
| |
37 |
# protected |
| |
38 |
# def deny_access |
| |
39 |
# ... |
| |
40 |
# end |
| |
41 |
# |
| |
42 |
# def show_errors(exception) |
| |
43 |
# exception.record.new_record? ? ... |
| |
44 |
# end |
| |
45 |
# end |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
46 |
def rescue_from(*klasses, &block) |
| |
47 |
options = klasses.extract_options! |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
48 |
|
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
49 |
unless options.has_key?(:with) |
| |
50 |
if block_given? |
| |
51 |
options[:with] = block |
| |
52 |
else |
| |
53 |
raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument." |
| |
54 |
end |
| |
55 |
end |
| |
56 |
|
| |
57 |
klasses.each do |klass| |
| |
58 |
key = if klass.is_a?(Class) && klass <= Exception |
| |
59 |
klass.name |
| |
60 |
elsif klass.is_a?(String) |
| |
61 |
klass |
| |
62 |
else |
| |
63 |
raise ArgumentError, "#{klass} is neither an Exception nor a String" |
| |
64 |
end |
| |
65 |
|
| |
66 |
# put the new handler at the end because the list is read in reverse |
| |
67 |
rescue_handlers << [key, options[:with]] |
| |
68 |
end |
| |
69 |
end |
| |
70 |
end |
| |
71 |
|
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
72 |
# Tries to rescue the exception by looking up and calling a registered handler. |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
73 |
def rescue_with_handler(exception) |
| |
74 |
if handler = handler_for_rescue(exception) |
| |
75 |
handler.arity != 0 ? handler.call(exception) : handler.call |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
76 |
true # don't rely on the return value of the handler |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
77 |
end |
| |
78 |
end |
| |
79 |
|
| |
80 |
def handler_for_rescue(exception) |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
81 |
# We go from right to left because pairs are pushed onto rescue_handlers |
| |
82 |
# as rescue_from declarations are found. |
|
983dc807
»
|
jeremy |
2008-11-06 |
Don't shadow local with bla... |
83 |
_, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler| |
|
259a7a84
»
|
lifo |
2008-10-04 |
Add tests for ActiveSupport... |
84 |
# The purpose of allowing strings in rescue_from is to support the |
| |
85 |
# declaration of handler associations for exception classes whose |
| |
86 |
# definition is yet unknown. |
| |
87 |
# |
| |
88 |
# Since this loop needs the constants it would be inconsistent to |
| |
89 |
# assume they should exist at this point. An early raised exception |
| |
90 |
# could trigger some other handler and the array could include |
| |
91 |
# precisely a string whose corresponding constant has not yet been |
| |
92 |
# seen. This is why we are tolerant to unknown constants. |
| |
93 |
# |
| |
94 |
# Note that this tolerance only matters if the exception was given as |
| |
95 |
# a string, otherwise a NameError will be raised by the interpreter |
| |
96 |
# itself when rescue_from CONSTANT is executed. |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
97 |
klass = self.class.const_get(klass_name) rescue nil |
| |
98 |
klass ||= klass_name.constantize rescue nil |
| |
99 |
exception.is_a?(klass) if klass |
| |
100 |
end |
| |
101 |
|
|
983dc807
»
|
jeremy |
2008-11-06 |
Don't shadow local with bla... |
102 |
case rescuer |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
103 |
when Symbol |
|
983dc807
»
|
jeremy |
2008-11-06 |
Don't shadow local with bla... |
104 |
method(rescuer) |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
105 |
when Proc |
|
983dc807
»
|
jeremy |
2008-11-06 |
Don't shadow local with bla... |
106 |
rescuer.bind(self) |
|
964dfc15
»
|
norbert |
2008-10-04 |
First draft of ActiveSuppor... |
107 |
end |
| |
108 |
end |
| |
109 |
end |
| |
110 |
end |