1
1
module AbstractController
2
+ class Error < StandardError ; end
3
+
4
+ class DoubleRenderError < Error
5
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \" redirect_to(...) and return\" ."
6
+
7
+ def initialize ( message = nil )
8
+ super ( message || DEFAULT_MESSAGE )
9
+ end
10
+ end
11
+
2
12
class Base
13
+
3
14
attr_internal :response_body
4
15
attr_internal :response_obj
5
16
attr_internal :action_name
6
17
7
- def self . process ( action )
8
- new . process ( action )
9
- end
18
+ class << self
19
+ attr_reader :abstract
20
+
21
+ def abstract!
22
+ @abstract = true
23
+ end
24
+
25
+ alias_method :abstract? , :abstract
26
+
27
+ def internal_methods
28
+ controller = self
29
+ controller = controller . superclass until controller . abstract?
30
+ controller . public_instance_methods ( true )
31
+ end
32
+
33
+ def process ( action )
34
+ new . process ( action . to_s )
35
+ end
10
36
11
- def self . inherited ( klass )
37
+ def hidden_actions
38
+ [ ]
39
+ end
40
+
41
+ def action_methods
42
+ @action_methods ||=
43
+ # All public instance methods of this class, including ancestors
44
+ public_instance_methods ( true ) . map { |m | m . to_s } . to_set -
45
+ # Except for public instance methods of Base and its ancestors
46
+ internal_methods . map { |m | m . to_s } +
47
+ # Be sure to include shadowed public instance methods of this class
48
+ public_instance_methods ( false ) . map { |m | m . to_s } -
49
+ # And always exclude explicitly hidden actions
50
+ hidden_actions
51
+ end
12
52
end
13
-
53
+
54
+ abstract!
55
+
14
56
def initialize
15
57
self . response_obj = { }
16
58
end
17
-
59
+
18
60
def process ( action_name )
19
61
unless respond_to_action? ( action_name )
20
62
raise ActionNotFound , "The action '#{ action_name } ' could not be found"
21
63
end
22
-
64
+
23
65
@_action_name = action_name
24
66
process_action
25
- self . response_obj [ :body ] = self . response_body
26
67
self
27
68
end
28
-
69
+
29
70
private
71
+
72
+ def action_methods
73
+ self . class . action_methods
74
+ end
75
+
76
+ # It is possible for respond_to?(action_name) to be false and
77
+ # respond_to?(:action_missing) to be false if respond_to_action?
78
+ # is overridden in a subclass. For instance, ActionController::Base
79
+ # overrides it to include the case where a template matching the
80
+ # action_name is found.
30
81
def process_action
31
- respond_to? ( action_name ) ? send ( action_name ) : send ( :action_missing , action_name )
82
+ if respond_to? ( action_name ) then send ( action_name )
83
+ elsif respond_to? ( :action_missing , true ) then action_missing ( action_name )
84
+ end
32
85
end
33
-
86
+
87
+ # Override this to change the conditions that will raise an
88
+ # ActionNotFound error. If you accept a difference case,
89
+ # you must handle it by also overriding process_action and
90
+ # handling the case.
34
91
def respond_to_action? ( action_name )
35
- respond_to ?( action_name ) || respond_to? ( :action_missing , true )
92
+ action_methods . include ?( action_name ) || respond_to? ( :action_missing , true )
36
93
end
37
94
end
38
- end
95
+ end
0 commit comments