class AbstractController::Base
different things depending on the context.
expected to provide their own render
method, since rendering means
using it directly, and subclasses (like ActionController::Base) are
AbstractController::Base is a low-level API. Nobody should be
= Abstract Controller Base
def self.supports_path?
may return false. An Email controller for example does not
a path. A subclass of +AbstractController::Base+
Returns true if the given controller is capable of rendering
def self.supports_path? true end
def _find_action_name(action_name)
* false - No valid method name could be found.
* string - The name of the method that handles the action
==== Returns
* action_name - An action name to find a method name for
==== Parameters
See method_for_action for more information.
It checks if the action name is valid and returns false otherwise.
handle the action.
Takes an action name and returns the name of the method that will
def _find_action_name(action_name) _valid_action_name?(action_name) && method_for_action(action_name) end
def _handle_action_missing(*args)
was found, #method_for_action will return "_handle_action_missing".
If the action name was not found, but a method called "action_missing"
def _handle_action_missing(*args) action_missing(@_action_name, *args) end
def _valid_action_name?(action_name)
def _valid_action_name?(action_name) !action_name.to_s.include? File::SEPARATOR end
def abstract!
Define a controller as abstract. See internal_methods for more
def abstract! @abstract = true end
def action_method?(name)
==== Parameters
it has a method defined in the controller.
Returns true if the name can be considered an action because
def action_method?(name) self.class.action_methods.include?(name) end
def action_methods
==== Returns
itself.
any methods that are internal, but still exist on the class
any internal methods (see internal_methods), adding back in
includes all public instance methods on a controller, less
A list of method names that should be considered actions. This
def action_methods @action_methods ||= begin # All public instance methods of this class, including ancestors # except for public instance methods of Base and its ancestors. methods = public_instance_methods(true) - internal_methods # Be sure to include shadowed public instance methods of this class. methods.concat(public_instance_methods(false)) methods.map!(&:to_s) methods.to_set end end
def action_methods
def action_methods self.class.action_methods end
def available_action?(action_name)
==== Parameters
through other means, for example, implicit render ones.
this method considers actions that are also available
false and available_action?("foo") returns true because
Notice that action_methods.include?("foo") may return
can be dispatched, false otherwise.
Returns true if a method for the action is available and
def available_action?(action_name) _find_action_name(action_name) end
def clear_action_methods!
them. ::clear_action_methods! allows you to do that, so next time
action_methods are cached and there is sometimes a need to refresh
def clear_action_methods! @action_methods = nil end
def controller_path
==== Returns
MyApp::MyPostsController.controller_path # => "my_app/my_posts"
end
class MyApp::MyPostsController < AbstractController::Base
Returns the full controller name, underscored, without the ending Controller.
def controller_path @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous? end
def controller_path
def controller_path self.class.controller_path end
def eager_load! # :nodoc:
def eager_load! # :nodoc: action_methods nil end
def inherited(klass) # :nodoc:
def inherited(klass) # :nodoc: # Define the abstract ivar on subclasses so that we don't get # uninitialized ivar warnings unless klass.instance_variable_defined?(:@abstract) klass.instance_variable_set(:@abstract, false) end super end
def inspect # :nodoc:
def inspect # :nodoc: "#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>" end
def internal_methods
declared on abstract classes are being removed.
a controller would normally be considered action methods, so methods
instance methods on that abstract class. Public instance methods of
abstract superclass of a controller, and gets a list of all public
A list of all internal methods for a controller. This finds the first
def internal_methods controller = self methods = [] until controller.abstract? methods += controller.public_instance_methods(false) controller = controller.superclass end controller.public_instance_methods(true) - methods end
def method_added(name)
def method_added(name) super clear_action_methods! end
def method_for_action(action_name)
* string - The name of the method that handles the action
==== Returns
* action_name - An action name to find a method name for
==== Parameters
returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised.
If none of these conditions are true, and +method_for_action+
the case.
also provide a method (like +_handle_method_missing+) to handle
If you override this method to handle additional cases, you may
with a template matching the action name is considered to exist.
that should be considered an action. For instance, an HTTP controller
Subclasses may override this method to add additional conditions
method and return "_handle_action_missing" if one is found.
a name that is not an action, it will look for an #action_missing
name as it receives. By default, if #method_for_action receives
handle the action. In normal cases, this method returns the same
Takes an action name and returns the name of the method that will
def method_for_action(action_name) if action_method?(action_name) action_name elsif respond_to?(:action_missing, true) "_handle_action_missing" end end
def performed?
+process_action+ callback needs to be terminated in
Tests if a response body is set. Used to determine if the
def performed? response_body end
def process(action, *args)
==== Returns
AbstractController::ActionNotFound error is raised.
#method_for_action. If no method can handle the action, then an
The actual method that is called is determined by calling
Calls the action going through the entire Action Dispatch stack.
def process(action, *args) @_action_name = action.to_s unless action_name = _find_action_name(@_action_name) raise ActionNotFound.new("The action '#{action}' could not be found for #{self.class.name}", self, action) end @_response_body = nil process_action(action_name, *args) end
def process_action(...)
Notice that the first argument is the method to be dispatched
is the intended way to override action dispatching.
behavior around processing an action. This, and not #process,
Call the action. Override this in a subclass to modify the
def process_action(...) send_action(...) end