1
1
# frozen_string_literal: true
2
2
3
+ # :markup: markdown
4
+
3
5
require "abstract_controller/error"
4
6
require "active_support/configurable"
5
7
require "active_support/descendants_tracker"
@@ -26,12 +28,12 @@ def corrections # :nodoc:
26
28
end
27
29
end
28
30
29
- # = Abstract Controller \ Base
31
+ # # Abstract Controller Base
30
32
#
31
- # AbstractController::Base is a low-level API. Nobody should be
32
- # using it directly, and subclasses (like ActionController::Base) are
33
- # expected to provide their own + render+ method, since rendering means
34
- # different things depending on the context.
33
+ # AbstractController::Base is a low-level API. Nobody should be using it
34
+ # directly, and subclasses (like ActionController::Base) are expected to provide
35
+ # their own ` render` method, since rendering means different things depending on
36
+ # the context.
35
37
class Base
36
38
##
37
39
# Returns the body of the HTTP response sent by the controller.
@@ -52,27 +54,26 @@ class << self
52
54
attr_reader :abstract
53
55
alias_method :abstract? , :abstract
54
56
55
- # Define a controller as abstract. See internal_methods for more
56
- # details.
57
+ # Define a controller as abstract. See internal_methods for more details.
57
58
def abstract!
58
59
@abstract = true
59
60
end
60
61
61
62
def inherited ( klass ) # :nodoc:
62
- # Define the abstract ivar on subclasses so that we don't get
63
- # uninitialized ivar warnings
63
+ # Define the abstract ivar on subclasses so that we don't get uninitialized ivar
64
+ # warnings
64
65
unless klass . instance_variable_defined? ( :@abstract )
65
66
klass . instance_variable_set ( :@abstract , false )
66
67
end
67
68
super
68
69
end
69
70
70
- # A list of all internal methods for a controller. This finds the first
71
- # abstract superclass of a controller, and gets a list of all public
72
- # instance methods on that abstract class. Public instance methods of
73
- # a controller would normally be considered action methods, so methods
74
- # declared on abstract classes are being removed.
75
- # (ActionController::Metal and ActionController::Base are defined as abstract)
71
+ # A list of all internal methods for a controller. This finds the first abstract
72
+ # superclass of a controller, and gets a list of all public instance methods on
73
+ # that abstract class. Public instance methods of a controller would normally be
74
+ # considered action methods, so methods declared on abstract classes are being
75
+ # removed. (ActionController::Metal and ActionController::Base are defined as
76
+ # abstract)
76
77
def internal_methods
77
78
controller = self
78
79
methods = [ ]
@@ -85,18 +86,18 @@ def internal_methods
85
86
controller . public_instance_methods ( true ) - methods
86
87
end
87
88
88
- # A list of method names that should be considered actions. This
89
- # includes all public instance methods on a controller, less
90
- # any internal methods (see internal_methods), adding back in
91
- # any methods that are internal, but still exist on the class
92
- # itself.
89
+ # A list of method names that should be considered actions. This includes all
90
+ # public instance methods on a controller, less any internal methods (see
91
+ # internal_methods), adding back in any methods that are internal, but still
92
+ # exist on the class itself.
93
+ #
94
+ # #### Returns
95
+ # * `Set` - A set of all methods that should be considered actions.
93
96
#
94
- # ==== Returns
95
- # * <tt>Set</tt> - A set of all methods that should be considered actions.
96
97
def action_methods
97
98
@action_methods ||= begin
98
- # All public instance methods of this class, including ancestors
99
- # except for public instance methods of Base and its ancestors.
99
+ # All public instance methods of this class, including ancestors except for
100
+ # public instance methods of Base and its ancestors.
100
101
methods = public_instance_methods ( true ) - internal_methods
101
102
# Be sure to include shadowed public instance methods of this class.
102
103
methods . concat ( public_instance_methods ( false ) )
@@ -105,23 +106,24 @@ def action_methods
105
106
end
106
107
end
107
108
108
- # action_methods are cached and there is sometimes a need to refresh
109
- # them. ::clear_action_methods! allows you to do that, so next time
110
- # you run action_methods, they will be recalculated.
109
+ # action_methods are cached and there is sometimes a need to refresh them.
110
+ # ::clear_action_methods! allows you to do that, so next time you run
111
+ # action_methods, they will be recalculated.
111
112
def clear_action_methods!
112
113
@action_methods = nil
113
114
end
114
115
115
116
# Returns the full controller name, underscored, without the ending Controller.
116
117
#
117
- # class MyApp::MyPostsController < AbstractController::Base
118
+ # class MyApp::MyPostsController < AbstractController::Base
119
+ #
120
+ # end
118
121
#
119
- # end
122
+ # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
120
123
#
121
- # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
124
+ # #### Returns
125
+ # * `String`
122
126
#
123
- # ==== Returns
124
- # * <tt>String</tt>
125
127
def controller_path
126
128
@controller_path ||= name . delete_suffix ( "Controller" ) . underscore unless anonymous?
127
129
end
@@ -142,12 +144,13 @@ def eager_load! # :nodoc:
142
144
143
145
# Calls the action going through the entire Action Dispatch stack.
144
146
#
145
- # The actual method that is called is determined by calling
146
- # #method_for_action. If no method can handle the action, then an
147
- # AbstractController::ActionNotFound error is raised.
147
+ # The actual method that is called is determined by calling #method_for_action.
148
+ # If no method can handle the action, then an AbstractController::ActionNotFound
149
+ # error is raised.
150
+ #
151
+ # #### Returns
152
+ # * `self`
148
153
#
149
- # ==== Returns
150
- # * <tt>self</tt>
151
154
def process ( action , ...)
152
155
@_action_name = action . to_s
153
156
@@ -170,31 +173,30 @@ def action_methods
170
173
self . class . action_methods
171
174
end
172
175
173
- # Returns true if a method for the action is available and
174
- # can be dispatched, false otherwise.
176
+ # Returns true if a method for the action is available and can be dispatched,
177
+ # false otherwise.
178
+ #
179
+ # Notice that `action_methods.include?("foo")` may return false and
180
+ # `available_action?("foo")` returns true because this method considers actions
181
+ # that are also available through other means, for example, implicit render
182
+ # ones.
175
183
#
176
- # Notice that <tt>action_methods.include?("foo")</tt> may return
177
- # false and <tt>available_action?("foo")</tt> returns true because
178
- # this method considers actions that are also available
179
- # through other means, for example, implicit render ones.
184
+ # #### Parameters
185
+ # * `action_name` - The name of an action to be tested
180
186
#
181
- # ==== Parameters
182
- # * <tt>action_name</tt> - The name of an action to be tested
183
187
def available_action? ( action_name )
184
188
_find_action_name ( action_name )
185
189
end
186
190
187
- # Tests if a response body is set. Used to determine if the
188
- # +process_action+ callback needs to be terminated in
189
- # AbstractController::Callbacks.
191
+ # Tests if a response body is set. Used to determine if the `process_action`
192
+ # callback needs to be terminated in AbstractController::Callbacks.
190
193
def performed?
191
194
response_body
192
195
end
193
196
194
- # Returns true if the given controller is capable of rendering
195
- # a path. A subclass of +AbstractController::Base+
196
- # may return false. An Email controller for example does not
197
- # support paths, only full URLs.
197
+ # Returns true if the given controller is capable of rendering a path. A
198
+ # subclass of `AbstractController::Base` may return false. An Email controller
199
+ # for example does not support paths, only full URLs.
198
200
def self . supports_path?
199
201
true
200
202
end
@@ -204,80 +206,83 @@ def inspect # :nodoc:
204
206
end
205
207
206
208
private
207
- # Returns true if the name can be considered an action because
208
- # it has a method defined in the controller.
209
+ # Returns true if the name can be considered an action because it has a method
210
+ # defined in the controller.
211
+ #
212
+ # #### Parameters
213
+ # * `name` - The name of an action to be tested
209
214
#
210
- # ==== Parameters
211
- # * <tt>name</tt> - The name of an action to be tested
212
215
def action_method? ( name )
213
216
self . class . action_methods . include? ( name )
214
217
end
215
218
216
- # Call the action. Override this in a subclass to modify the
217
- # behavior around processing an action. This, and not #process,
218
- # is the intended way to override action dispatching.
219
+ # Call the action. Override this in a subclass to modify the behavior around
220
+ # processing an action. This, and not #process, is the intended way to override
221
+ # action dispatching.
219
222
#
220
- # Notice that the first argument is the method to be dispatched
221
- # which is *not* necessarily the same as the action name.
223
+ # Notice that the first argument is the method to be dispatched which is **not**
224
+ # necessarily the same as the action name.
222
225
def process_action ( ...)
223
226
send_action ( ...)
224
227
end
225
228
226
- # Actually call the method associated with the action. Override
227
- # this method if you wish to change how action methods are called,
228
- # not to add additional behavior around it. For example, you would
229
- # override #send_action if you want to inject arguments into the
230
- # method.
229
+ # Actually call the method associated with the action. Override this method if
230
+ # you wish to change how action methods are called, not to add additional
231
+ # behavior around it. For example, you would override #send_action if you want
232
+ # to inject arguments into the method.
231
233
alias send_action send
232
234
233
- # If the action name was not found, but a method called "action_missing"
234
- # was found, #method_for_action will return "_handle_action_missing".
235
- # This method calls #action_missing with the current action name.
235
+ # If the action name was not found, but a method called "action_missing" was
236
+ # found, #method_for_action will return "_handle_action_missing". This method
237
+ # calls #action_missing with the current action name.
236
238
def _handle_action_missing ( *args )
237
239
action_missing ( @_action_name , *args )
238
240
end
239
241
240
- # Takes an action name and returns the name of the method that will
241
- # handle the action.
242
+ # Takes an action name and returns the name of the method that will handle the
243
+ # action.
242
244
#
243
245
# It checks if the action name is valid and returns false otherwise.
244
246
#
245
247
# See method_for_action for more information.
246
248
#
247
- # ==== Parameters
248
- # * <tt>action_name</tt> - An action name to find a method name for
249
+ # #### Parameters
250
+ # * `action_name` - An action name to find a method name for
251
+ #
252
+ #
253
+ # #### Returns
254
+ # * `string` - The name of the method that handles the action
255
+ # * false - No valid method name could be found.
249
256
#
250
- # ==== Returns
251
- # * <tt>string</tt> - The name of the method that handles the action
252
- # * false - No valid method name could be found.
253
- # Raise +AbstractController::ActionNotFound+.
257
+ # Raise `AbstractController::ActionNotFound`.
254
258
def _find_action_name ( action_name )
255
259
_valid_action_name? ( action_name ) && method_for_action ( action_name )
256
260
end
257
261
258
- # Takes an action name and returns the name of the method that will
259
- # handle the action. In normal cases, this method returns the same
260
- # name as it receives. By default, if #method_for_action receives
261
- # a name that is not an action, it will look for an #action_missing
262
- # method and return "_handle_action_missing" if one is found.
262
+ # Takes an action name and returns the name of the method that will handle the
263
+ # action. In normal cases, this method returns the same name as it receives. By
264
+ # default, if #method_for_action receives a name that is not an action, it will
265
+ # look for an #action_missing method and return "_handle_action_missing" if one
266
+ # is found.
267
+ #
268
+ # Subclasses may override this method to add additional conditions that should
269
+ # be considered an action. For instance, an HTTP controller with a template
270
+ # matching the action name is considered to exist.
271
+ #
272
+ # If you override this method to handle additional cases, you may also provide a
273
+ # method (like `_handle_method_missing`) to handle the case.
263
274
#
264
- # Subclasses may override this method to add additional conditions
265
- # that should be considered an action. For instance, an HTTP controller
266
- # with a template matching the action name is considered to exist.
275
+ # If none of these conditions are true, and `method_for_action` returns `nil`,
276
+ # an `AbstractController::ActionNotFound` exception will be raised.
267
277
#
268
- # If you override this method to handle additional cases, you may
269
- # also provide a method (like +_handle_method_missing+) to handle
270
- # the case.
278
+ # #### Parameters
279
+ # * `action_name` - An action name to find a method name for
271
280
#
272
- # If none of these conditions are true, and +method_for_action+
273
- # returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised.
274
281
#
275
- # ==== Parameters
276
- # * <tt>action_name</tt> - An action name to find a method name for
282
+ # #### Returns
283
+ # * `string` - The name of the method that handles the action
284
+ # * `nil` - No method name could be found.
277
285
#
278
- # ==== Returns
279
- # * <tt>string</tt> - The name of the method that handles the action
280
- # * <tt>nil</tt> - No method name could be found.
281
286
def method_for_action ( action_name )
282
287
if action_method? ( action_name )
283
288
action_name
0 commit comments