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