2009-12-13 01:50:12 +00:00
require " abstract_controller/base "
2010-06-02 20:56:41 +00:00
require " action_view "
2009-02-27 19:42:13 +00:00
2009-02-25 01:25:21 +00:00
module AbstractController
2009-12-13 00:48:34 +00: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
end
2010-03-10 21:11:48 +00:00
# This is a class to fix I18n global state. Whenever you provide I18n.locale during a request,
# it will trigger the lookup_context and consequently expire the cache.
class I18nProxy < :: I18n :: Config #:nodoc:
2011-01-19 22:42:10 +00:00
attr_reader :original_config , :lookup_context
2010-03-10 21:11:48 +00:00
2011-01-19 22:42:10 +00:00
def initialize ( original_config , lookup_context )
original_config = original_config . original_config if original_config . respond_to? ( :original_config )
@original_config , @lookup_context = original_config , lookup_context
2010-03-10 21:11:48 +00:00
end
def locale
2011-01-19 22:42:10 +00:00
@original_config . locale
2010-03-10 21:11:48 +00:00
end
def locale = ( value )
2010-04-12 08:50:27 +00:00
@lookup_context . locale = value
2010-03-10 21:11:48 +00:00
end
end
2010-03-08 10:32:01 +00:00
module Rendering
extend ActiveSupport :: Concern
include AbstractController :: ViewPaths
2011-05-06 12:32:48 +00:00
included do
2011-12-24 08:59:28 +00:00
class_attribute :protected_instance_variables
2011-05-06 12:32:48 +00:00
self . protected_instance_variables = [ ]
end
2010-03-10 21:11:48 +00:00
# Overwrite process to setup I18n proxy.
def process ( * ) #:nodoc:
old_config , I18n . config = I18n . config , I18nProxy . new ( I18n . config , lookup_context )
super
ensure
I18n . config = old_config
end
2010-03-19 01:12:04 +00:00
module ClassMethods
def view_context_class
@view_context_class || = begin
2012-06-29 09:33:37 +00:00
routes = respond_to? ( :_routes ) && _routes
helpers = respond_to? ( :_helpers ) && _helpers
2012-10-27 14:03:18 +00:00
2012-06-29 09:33:37 +00:00
Class . new ( ActionView :: Base ) do
if routes
include routes . url_helpers
include routes . mounted_helpers
end
if helpers
include helpers
end
end
2010-03-19 01:12:04 +00:00
end
end
end
2011-05-06 12:32:48 +00:00
attr_internal_writer :view_context_class
2010-03-19 01:12:04 +00:00
def view_context_class
2011-12-08 14:23:23 +00:00
@_view_context_class || = self . class . view_context_class
2010-03-19 05:21:25 +00:00
end
2009-06-09 00:41:08 +00:00
# An instance of a view class. The default view class is ActionView::Base
#
# The view class must have the following methods:
2010-03-19 01:12:04 +00:00
# View.new[lookup_context, assigns, controller]
2010-03-08 10:32:01 +00:00
# Create a new ActionView instance for a controller
2010-03-19 01:12:04 +00:00
# View#render[options]
2010-03-08 10:32:01 +00:00
# Returns String with the rendered template
2009-06-09 00:41:08 +00:00
#
2010-02-16 18:45:59 +00:00
# Override this method in a module to change the default behavior.
2009-08-06 22:45:40 +00:00
def view_context
2011-05-01 10:56:04 +00:00
view_context_class . new ( view_renderer , view_assigns , self )
end
# Returns an object that is able to render templates.
def view_renderer
2011-05-06 12:32:48 +00:00
@_view_renderer || = ActionView :: Renderer . new ( lookup_context )
2009-02-25 01:25:21 +00:00
end
2009-05-28 14:49:02 +00:00
2010-03-12 19:39:53 +00:00
# Normalize arguments, options and then delegates render_to_body and
# sticks the result in self.response_body.
2010-01-20 13:21:27 +00:00
def render ( * args , & block )
2011-04-18 06:12:51 +00:00
options = _normalize_render ( * args , & block )
self . response_body = render_to_body ( options )
2010-04-05 02:49:12 +00:00
end
# Raw rendering of a template to a string. Just convert the results of
2011-04-18 06:12:51 +00:00
# render_response into a String.
2010-04-05 02:49:12 +00:00
# :api: plugin
def render_to_string ( * args , & block )
2011-04-18 06:12:51 +00:00
options = _normalize_render ( * args , & block )
2011-04-19 09:54:12 +00:00
render_to_body ( options )
2009-03-18 22:58:47 +00:00
end
2009-05-28 14:49:02 +00:00
2009-04-21 23:02:30 +00:00
# Raw rendering of a template to a Rack-compatible body.
2009-03-19 22:45:48 +00:00
# :api: plugin
2009-04-17 23:34:49 +00:00
def render_to_body ( options = { } )
2010-03-08 10:32:01 +00:00
_process_options ( options )
_render_template ( options )
2009-02-27 19:42:13 +00:00
end
2010-03-08 10:32:01 +00:00
# Find and renders a template based on the options given.
2010-03-12 19:39:53 +00:00
# :api: private
def _render_template ( options ) #:nodoc:
2012-03-17 14:08:49 +00:00
lookup_context . rendered_format = nil if options [ :formats ]
2011-05-03 14:51:08 +00:00
view_renderer . render ( view_context , options )
2009-05-28 14:49:02 +00:00
end
2009-02-27 19:42:13 +00:00
2012-01-07 11:44:47 +00:00
DEFAULT_PROTECTED_INSTANCE_VARIABLES = [
:@_action_name , :@_response_body , :@_formats , :@_prefixes , :@_config ,
:@_view_context_class , :@_view_renderer , :@_lookup_context
]
2011-05-06 12:32:48 +00:00
2010-03-18 22:52:43 +00:00
# This method should return a hash with assigns.
# You can overwrite this configuration per controller.
# :api: public
def view_assigns
hash = { }
2012-01-07 11:44:47 +00:00
variables = instance_variables
2011-05-06 12:32:48 +00:00
variables -= protected_instance_variables
variables -= DEFAULT_PROTECTED_INSTANCE_VARIABLES
2012-01-07 12:30:36 +00:00
variables . each { | name | hash [ name [ 1 .. - 1 ] ] = instance_variable_get ( name ) }
2010-03-18 22:52:43 +00:00
hash
end
2011-10-02 09:28:48 +00:00
private
2011-04-18 06:12:51 +00:00
# Normalize args and options.
# :api: private
def _normalize_render ( * args , & block )
options = _normalize_args ( * args , & block )
_normalize_options ( options )
options
end
# Normalize args by converting render "foo" to render :action => "foo" and
2010-03-08 15:32:40 +00:00
# render "foo/bar" to render :file => "foo/bar".
2011-04-18 06:12:51 +00:00
# :api: plugin
2010-03-08 02:23:16 +00:00
def _normalize_args ( action = nil , options = { } )
2010-01-22 16:57:36 +00:00
case action
2010-03-08 10:32:01 +00:00
when NilClass
2010-01-22 16:57:36 +00:00
when Hash
2010-11-19 01:20:54 +00:00
options = action
2010-01-22 16:57:36 +00:00
when String , Symbol
action = action . to_s
2010-03-08 15:32:40 +00:00
key = action . include? ( ?/ ) ? :file : :action
options [ key ] = action
2010-03-08 10:32:01 +00:00
else
2010-11-19 01:27:05 +00:00
options [ :partial ] = action
2010-01-22 16:57:36 +00:00
end
options
end
2011-04-18 06:12:51 +00:00
# Normalize options.
# :api: plugin
2010-03-08 02:23:16 +00:00
def _normalize_options ( options )
2010-03-08 10:32:01 +00:00
if options [ :partial ] == true
options [ :partial ] = action_name
end
2010-03-08 02:23:16 +00:00
2011-04-15 19:11:54 +00:00
if ( options . keys & [ :partial , :file , :template ] ) . empty?
2010-09-17 20:39:14 +00:00
options [ :prefixes ] || = _prefixes
2009-10-19 00:52:36 +00:00
end
2010-03-08 10:32:01 +00:00
options [ :template ] || = ( options [ :action ] || action_name ) . to_s
options
2010-02-24 21:06:24 +00:00
end
2011-04-18 06:12:51 +00:00
# Process extra options.
# :api: plugin
2010-03-08 10:32:01 +00:00
def _process_options ( options )
2009-10-21 17:55:47 +00:00
end
2009-02-25 01:25:21 +00:00
end
2010-02-01 02:32:28 +00:00
end