2009-05-14 04:56:07 -04:00
require 'active_support/core_ext/module/attr_internal'
2009-02-24 20:25:21 -05:00
module AbstractController
2009-05-12 19:21:34 -04:00
class Error < StandardError ; end
2009-05-28 10:49:02 -04:00
2009-05-12 19:21:34 -04:00
class DoubleRenderError < Error
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 \" . "
def initialize ( message = nil )
super ( message || DEFAULT_MESSAGE )
end
2009-05-28 10:49:02 -04:00
end
2009-02-24 20:25:21 -05:00
class Base
attr_internal :response_body
attr_internal :response_obj
2009-02-27 14:42:13 -05:00
attr_internal :action_name
2009-04-30 18:13:40 -04:00
class << self
2009-05-28 10:49:02 -04:00
attr_reader :abstract
2009-04-30 18:13:40 -04:00
def abstract!
@abstract = true
end
2009-05-28 10:49:02 -04:00
2009-04-30 18:13:40 -04:00
alias_method :abstract? , :abstract
2009-05-14 18:30:35 -04:00
def inherited ( klass )
:: AbstractController :: Base . subclasses << klass . to_s
super
end
def subclasses
@subclasses || = [ ]
end
2009-05-28 10:49:02 -04:00
2009-04-30 18:13:40 -04:00
def internal_methods
controller = self
controller = controller . superclass until controller . abstract?
controller . public_instance_methods ( true )
end
2009-05-28 10:49:02 -04:00
2009-04-30 18:13:40 -04:00
def process ( action )
2009-05-01 19:01:37 -04:00
new . process ( action . to_s )
2009-04-30 18:13:40 -04:00
end
def hidden_actions
[ ]
end
2009-05-28 10:49:02 -04:00
2009-04-30 18:13:40 -04:00
def action_methods
@action_methods || =
# All public instance methods of this class, including ancestors
2009-05-01 19:01:37 -04:00
public_instance_methods ( true ) . map { | m | m . to_s } . to_set -
2009-04-30 18:13:40 -04:00
# Except for public instance methods of Base and its ancestors
2009-05-01 19:01:37 -04:00
internal_methods . map { | m | m . to_s } +
2009-04-30 18:13:40 -04:00
# Be sure to include shadowed public instance methods of this class
2009-05-01 19:01:37 -04:00
public_instance_methods ( false ) . map { | m | m . to_s } -
2009-04-30 18:13:40 -04:00
# And always exclude explicitly hidden actions
hidden_actions
end
2009-02-24 20:25:21 -05:00
end
2009-05-28 10:49:02 -04:00
2009-04-30 18:13:40 -04:00
abstract!
2009-05-28 10:49:02 -04:00
2009-02-24 20:25:21 -05:00
def initialize
self . response_obj = { }
end
2009-05-28 10:49:02 -04:00
2009-05-23 03:39:32 -04:00
def process ( action )
@_action_name = action_name = action . to_s
2009-05-14 20:25:10 -04:00
2009-05-15 18:57:12 -04:00
unless action_name = method_for_action ( action_name )
2009-05-23 03:39:32 -04:00
raise ActionNotFound , " The action ' #{ action } ' could not be found "
2009-03-17 21:04:22 -04:00
end
2009-05-15 18:57:12 -04:00
process_action ( action_name )
2009-02-24 20:25:21 -05:00
self
end
2009-05-28 10:49:02 -04:00
2009-03-17 21:04:22 -04:00
private
2009-04-30 18:13:40 -04:00
def action_methods
self . class . action_methods
end
2009-05-28 10:49:02 -04:00
2009-05-14 20:25:10 -04:00
def action_method? ( action )
action_methods . include? ( action )
end
2009-05-28 10:49:02 -04:00
2009-04-29 20:32:39 -04:00
# It is possible for respond_to?(action_name) to be false and
# respond_to?(:action_missing) to be false if respond_to_action?
# is overridden in a subclass. For instance, ActionController::Base
# overrides it to include the case where a template matching the
# action_name is found.
2009-05-15 18:57:12 -04:00
def process_action ( method_name )
2009-05-27 18:59:14 -04:00
send_action ( method_name )
2009-03-17 21:04:22 -04:00
end
2009-05-15 18:57:12 -04:00
2009-05-27 18:59:14 -04:00
alias send_action send
2009-05-15 18:57:12 -04:00
def _handle_action_missing
action_missing ( @_action_name )
end
2009-04-29 20:32:39 -04:00
# Override this to change the conditions that will raise an
# ActionNotFound error. If you accept a difference case,
# you must handle it by also overriding process_action and
# handling the case.
2009-05-15 18:57:12 -04:00
def method_for_action ( action_name )
if action_method? ( action_name ) then action_name
elsif respond_to? ( :action_missing , true ) then " _handle_action_missing "
end
2009-02-27 22:25:45 -05:00
end
2009-02-24 20:25:21 -05:00
end
2009-05-28 10:49:02 -04:00
end