Finally moved the find template logic to the views.
This commit is contained in:
parent
34b2180451
commit
0a85380966
@ -264,7 +264,7 @@ def _layout
|
||||
|
||||
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
||||
def _layout
|
||||
if template_exists?("#{_implied_layout_name}", :_prefix => #{_prefix.inspect})
|
||||
if template_exists?("#{_implied_layout_name}", #{_prefix.inspect})
|
||||
"#{_implied_layout_name}"
|
||||
else
|
||||
super
|
||||
@ -277,7 +277,9 @@ def _layout
|
||||
end
|
||||
end
|
||||
|
||||
def render_to_body(options)
|
||||
def _normalize_options(options)
|
||||
super
|
||||
|
||||
if _include_layout?(options)
|
||||
layout = options.key?(:layout) ? options[:layout] : :default
|
||||
value = _layout_for_option(layout)
|
||||
@ -288,7 +290,6 @@ def render_to_body(options)
|
||||
# TODO Revisit this. :layout with :partial from controllers are not the same as in views
|
||||
options[:layout] = view_context._find_layout(options[:layout]) if options.key?(:partial)
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -10,7 +10,7 @@ def initialize(message = nil)
|
||||
end
|
||||
end
|
||||
|
||||
module Rendering
|
||||
module ViewPaths
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
@ -21,80 +21,12 @@ module Rendering
|
||||
delegate :formats, :formats=, :to => :template_lookup
|
||||
delegate :_view_paths, :to => :'self.class'
|
||||
|
||||
# An instance of a view class. The default view class is ActionView::Base
|
||||
#
|
||||
# The view class must have the following methods:
|
||||
# View.for_controller[controller] Create a new ActionView instance for a
|
||||
# controller
|
||||
# View#render_partial[options]
|
||||
# - responsible for setting options[:_template]
|
||||
# - Returns String with the rendered partial
|
||||
# options<Hash>:: see _render_partial in ActionView::Base
|
||||
# View#render_template[template, layout, options, partial]
|
||||
# - Returns String with the rendered template
|
||||
# template<ActionView::Template>:: The template to render
|
||||
# layout<ActionView::Template>:: The layout to render around the template
|
||||
# options<Hash>:: See _render_template_with_layout in ActionView::Base
|
||||
# partial<Boolean>:: Whether or not the template to render is a partial
|
||||
#
|
||||
# Override this method in a module to change the default behavior.
|
||||
def view_context
|
||||
@_view_context ||= ActionView::Base.for_controller(self)
|
||||
end
|
||||
|
||||
# Mostly abstracts the fact that calling render twice is a DoubleRenderError.
|
||||
# Delegates render_to_body and sticks the result in self.response_body.
|
||||
def render(*args, &block)
|
||||
options = _normalize_args(*args, &block)
|
||||
_normalize_options(options)
|
||||
self.response_body = render_to_body(options)
|
||||
end
|
||||
|
||||
# Raw rendering of a template to a Rack-compatible body.
|
||||
#
|
||||
# ==== Options
|
||||
# _partial_object<Object>:: The object that is being rendered. If this
|
||||
# exists, we are in the special case of rendering an object as a partial.
|
||||
#
|
||||
# :api: plugin
|
||||
def render_to_body(options = {})
|
||||
# TODO: Refactor so we can just use the normal template logic for this
|
||||
if options.key?(:partial)
|
||||
_render_partial(options)
|
||||
else
|
||||
_determine_template(options)
|
||||
_render_template(options)
|
||||
end
|
||||
end
|
||||
|
||||
# Raw rendering of a template to a string. Just convert the results of
|
||||
# render_to_body into a String.
|
||||
#
|
||||
# :api: plugin
|
||||
def render_to_string(options={})
|
||||
_normalize_options(options)
|
||||
AbstractController::Rendering.body_to_s(render_to_body(options))
|
||||
end
|
||||
|
||||
# Renders the template from an object.
|
||||
#
|
||||
# ==== Options
|
||||
# _template<ActionView::Template>:: The template to render
|
||||
# _layout<ActionView::Template>:: The layout to wrap the template in (optional)
|
||||
def _render_template(options)
|
||||
view_context.render_template(options)
|
||||
end
|
||||
|
||||
# Renders the given partial.
|
||||
#
|
||||
# ==== Options
|
||||
# partial<String|Object>:: The partial name or the object to be rendered
|
||||
def _render_partial(options)
|
||||
view_context.render_partial(options)
|
||||
end
|
||||
|
||||
def template_lookup
|
||||
@template_lookup ||= ActionView::Template::Lookup.new(_view_paths, details_for_render)
|
||||
@template_lookup ||= ActionView::Template::Lookup.new(_view_paths, details_for_lookup)
|
||||
end
|
||||
|
||||
def details_for_lookup
|
||||
{ }
|
||||
end
|
||||
|
||||
# The list of view paths for this controller. See ActionView::ViewPathSet for
|
||||
@ -111,101 +43,14 @@ def prepend_view_path(path)
|
||||
template_lookup.view_paths.unshift(*path)
|
||||
end
|
||||
|
||||
# The prefix used in render "foo" shortcuts.
|
||||
def _prefix
|
||||
controller_path
|
||||
protected
|
||||
|
||||
def template_exists?(*args)
|
||||
template_lookup.exists?(*args)
|
||||
end
|
||||
|
||||
# Return a string representation of a Rack-compatible response body.
|
||||
def self.body_to_s(body)
|
||||
if body.respond_to?(:to_str)
|
||||
body
|
||||
else
|
||||
strings = []
|
||||
body.each { |part| strings << part.to_s }
|
||||
body.close if body.respond_to?(:close)
|
||||
strings.join
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Normalize options, by converting render "foo" to render :template => "prefix/foo"
|
||||
# and render "/foo" to render :file => "/foo".
|
||||
def _normalize_args(action=nil, options={})
|
||||
case action
|
||||
when Hash
|
||||
options, action = action, nil
|
||||
when String, Symbol
|
||||
action = action.to_s
|
||||
case action.index("/")
|
||||
when NilClass
|
||||
options[:_prefix] = _prefix
|
||||
options[:_template_name] = action
|
||||
when 0
|
||||
options[:file] = action
|
||||
else
|
||||
options[:template] = action
|
||||
end
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def _normalize_options(options)
|
||||
end
|
||||
|
||||
# Take in a set of options and determine the template to render
|
||||
#
|
||||
# ==== Options
|
||||
# _template<ActionView::Template>:: If this is provided, the search is over
|
||||
# _template_name<#to_s>:: The name of the template to look up. Otherwise,
|
||||
# use the current action name.
|
||||
# _prefix<String>:: The prefix to look inside of. In a file system, this corresponds
|
||||
# to a directory.
|
||||
# _partial<TrueClass, FalseClass>:: Whether or not the file to look up is a partial
|
||||
def _determine_template(options)
|
||||
if options.key?(:text)
|
||||
options[:_template] = ActionView::Template::Text.new(options[:text], format_for_text)
|
||||
elsif options.key?(:inline)
|
||||
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
|
||||
template = ActionView::Template.new(options[:inline], "inline template", handler, {})
|
||||
options[:_template] = template
|
||||
elsif options.key?(:template)
|
||||
options[:_template_name] = options[:template]
|
||||
elsif options.key?(:file)
|
||||
options[:_template_name] = options[:file]
|
||||
end
|
||||
name = (options[:_template_name] || options[:action] || action_name).to_s
|
||||
options[:_prefix] ||= _prefix if (options.keys & [:partial, :file, :template]).empty?
|
||||
|
||||
details = _normalize_details(options)
|
||||
template_lookup.details = details
|
||||
|
||||
options[:_template] ||= find_template(name, options)
|
||||
end
|
||||
|
||||
def details_for_render
|
||||
{ }
|
||||
end
|
||||
|
||||
def _normalize_details(options)
|
||||
details = template_lookup.details
|
||||
details[:formats] = Array(options[:format]) if options[:format]
|
||||
details[:locale] = Array(options[:locale]) if options[:locale]
|
||||
details
|
||||
end
|
||||
|
||||
def find_template(name, options)
|
||||
template_lookup.find(name, options[:_prefix], options[:_partial])
|
||||
end
|
||||
|
||||
def template_exists?(name, options)
|
||||
template_lookup.exists?(name, options[:_prefix], options[:_partial])
|
||||
end
|
||||
|
||||
def format_for_text
|
||||
Mime[:text]
|
||||
def find_template(*args)
|
||||
template_lookup.find(*args)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
@ -245,4 +90,123 @@ def view_paths=(paths)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Rendering
|
||||
extend ActiveSupport::Concern
|
||||
include AbstractController::ViewPaths
|
||||
|
||||
# An instance of a view class. The default view class is ActionView::Base
|
||||
#
|
||||
# The view class must have the following methods:
|
||||
# View.for_controller[controller]
|
||||
# Create a new ActionView instance for a controller
|
||||
# View#render_template[options]
|
||||
# Returns String with the rendered template
|
||||
#
|
||||
# Override this method in a module to change the default behavior.
|
||||
def view_context
|
||||
@_view_context ||= ActionView::Base.for_controller(self)
|
||||
end
|
||||
|
||||
# Mostly abstracts the fact that calling render twice is a DoubleRenderError.
|
||||
# Delegates render_to_body and sticks the result in self.response_body.
|
||||
def render(*args, &block)
|
||||
options = _normalize_args(*args, &block)
|
||||
_normalize_options(options)
|
||||
self.response_body = render_to_body(options)
|
||||
end
|
||||
|
||||
# Raw rendering of a template to a Rack-compatible body.
|
||||
# :api: plugin
|
||||
def render_to_body(options = {})
|
||||
_process_options(options)
|
||||
_render_template(options)
|
||||
end
|
||||
|
||||
# Raw rendering of a template to a string. Just convert the results of
|
||||
# render_to_body into a String.
|
||||
# :api: plugin
|
||||
def render_to_string(options={})
|
||||
_normalize_options(options)
|
||||
AbstractController::Rendering.body_to_s(render_to_body(options))
|
||||
end
|
||||
|
||||
# Find and renders a template based on the options given.
|
||||
def _render_template(options)
|
||||
view_context.render_template(options) { |template| _with_template_hook(template) }
|
||||
end
|
||||
|
||||
# The prefix used in render "foo" shortcuts.
|
||||
def _prefix
|
||||
controller_path
|
||||
end
|
||||
|
||||
# Return a string representation of a Rack-compatible response body.
|
||||
def self.body_to_s(body)
|
||||
if body.respond_to?(:to_str)
|
||||
body
|
||||
else
|
||||
strings = []
|
||||
body.each { |part| strings << part.to_s }
|
||||
body.close if body.respond_to?(:close)
|
||||
strings.join
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Normalize options, by converting render "foo" to render :template => "prefix/foo"
|
||||
# and render "/foo" to render :file => "/foo".
|
||||
def _normalize_args(action=nil, options={})
|
||||
case action
|
||||
when NilClass
|
||||
when Hash
|
||||
options, action = action, nil
|
||||
when String, Symbol
|
||||
action = action.to_s
|
||||
case action.index("/")
|
||||
when NilClass
|
||||
options[:action] = action
|
||||
when 0
|
||||
options[:file] = action
|
||||
else
|
||||
options[:template] = action
|
||||
end
|
||||
else
|
||||
options.merge!(:partial => action)
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def _normalize_options(options)
|
||||
if options[:partial] == true
|
||||
options[:partial] = action_name
|
||||
end
|
||||
|
||||
if (options.keys & [:partial, :file, :template]).empty?
|
||||
options[:_prefix] ||= _prefix
|
||||
end
|
||||
|
||||
options[:template] ||= (options[:action] || action_name).to_s
|
||||
|
||||
details = _normalize_details(options)
|
||||
template_lookup.details = details
|
||||
options
|
||||
end
|
||||
|
||||
def _normalize_details(options)
|
||||
details = template_lookup.details
|
||||
details[:formats] = Array(options[:format]) if options[:format]
|
||||
details[:locale] = Array(options[:locale]) if options[:locale]
|
||||
details
|
||||
end
|
||||
|
||||
def _process_options(options)
|
||||
end
|
||||
|
||||
def _with_template_hook(template)
|
||||
self.formats = template.details[:formats]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -49,14 +49,19 @@ def process_action(*)
|
||||
super
|
||||
end
|
||||
|
||||
def render_to_body(options)
|
||||
if options.is_a?(Hash) && options.key?(:template)
|
||||
options[:template].sub!(/^\//, '')
|
||||
def _normalize_options(options)
|
||||
# TODO Deprecate this. Rails 2.x allowed to give a template as action.
|
||||
if options[:action] && options[:action].to_s.include?(?/)
|
||||
options[:template] = options.delete(:action)
|
||||
end
|
||||
|
||||
options[:text] = nil if options.delete(:nothing) == true
|
||||
options[:text] = " " if options.key?(:text) && options[:text].nil?
|
||||
super
|
||||
end
|
||||
|
||||
def render_to_body(options)
|
||||
options[:template].sub!(/^\//, '') if options.key?(:template)
|
||||
super || " "
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,7 @@ def default_render
|
||||
|
||||
def method_for_action(action_name)
|
||||
super || begin
|
||||
if template_exists?(action_name.to_s, :_prefix => controller_path)
|
||||
if template_exists?(action_name.to_s, _prefix)
|
||||
"default_render"
|
||||
end
|
||||
end
|
||||
|
@ -6,46 +6,20 @@ module Rendering
|
||||
include AbstractController::Rendering
|
||||
|
||||
def process(*)
|
||||
self.formats = request.formats.map {|x| x.to_sym }
|
||||
self.formats = request.formats.map { |x| x.to_sym }
|
||||
super
|
||||
end
|
||||
|
||||
def render(*args)
|
||||
raise ::AbstractController::DoubleRenderError if response_body
|
||||
args << {} unless args.last.is_a?(Hash)
|
||||
super(*args)
|
||||
self.content_type ||= args.last[:_template].mime_type.to_s
|
||||
response_body
|
||||
end
|
||||
|
||||
def render_to_body(options)
|
||||
_process_options(options)
|
||||
super
|
||||
response_body
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _render_partial(options)
|
||||
options[:partial] = action_name if options[:partial] == true
|
||||
options[:_details] = details_for_render
|
||||
super
|
||||
end
|
||||
|
||||
def format_for_text
|
||||
formats.first
|
||||
end
|
||||
|
||||
def _normalize_args(action=nil, options={}, &blk)
|
||||
case action
|
||||
when NilClass
|
||||
when Hash
|
||||
options = super(action.delete(:action), action)
|
||||
when String, Symbol
|
||||
options = super
|
||||
else
|
||||
options.merge!(:partial => action)
|
||||
end
|
||||
|
||||
options = super
|
||||
options[:update] = blk if block_given?
|
||||
options
|
||||
end
|
||||
@ -64,9 +38,18 @@ def _normalize_options(options)
|
||||
|
||||
def _process_options(options)
|
||||
status, content_type, location = options.values_at(:status, :content_type, :location)
|
||||
|
||||
self.status = status if status
|
||||
self.content_type = content_type if content_type
|
||||
self.headers["Location"] = url_for(location) if location
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def _with_template_hook(template)
|
||||
super
|
||||
self.content_type ||= template.mime_type.to_s
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -24,18 +24,8 @@ def render(options = {}, locals = {}, &block) #:nodoc:
|
||||
return _render_partial(options)
|
||||
end
|
||||
|
||||
template = if options[:file]
|
||||
find(options[:file])
|
||||
elsif options[:inline]
|
||||
handler = Template.handler_class_for_extension(options[:type] || "erb")
|
||||
Template.new(options[:inline], "inline template", handler, {})
|
||||
elsif options[:text]
|
||||
Template::Text.new(options[:text])
|
||||
end
|
||||
|
||||
if template
|
||||
_render_template(template, layout, :locals => options[:locals])
|
||||
end
|
||||
template = _determine_template(options)
|
||||
_render_template(template, layout, :locals => options[:locals]) if template
|
||||
when :update
|
||||
update_page(&block)
|
||||
else
|
||||
@ -87,8 +77,28 @@ def _layout_for(name = nil, &block)
|
||||
# _layout:: The layout, if any, to wrap the Template in
|
||||
def render_template(options)
|
||||
_evaluate_assigns_and_ivars
|
||||
template, layout = options.values_at(:_template, :layout)
|
||||
_render_template(template, layout, options)
|
||||
if options.key?(:partial)
|
||||
_render_partial(options)
|
||||
else
|
||||
template = _determine_template(options)
|
||||
yield template if block_given?
|
||||
_render_template(template, options[:layout], options)
|
||||
end
|
||||
end
|
||||
|
||||
def _determine_template(options)
|
||||
if options.key?(:inline)
|
||||
handler = Template.handler_class_for_extension(options[:type] || "erb")
|
||||
Template.new(options[:inline], "inline template", handler, {})
|
||||
elsif options.key?(:text)
|
||||
Template::Text.new(options[:text], self.formats.try(:first))
|
||||
elsif options.key?(:_template)
|
||||
options[:_template]
|
||||
elsif options.key?(:file)
|
||||
find(options[:file], options[:_prefix])
|
||||
elsif options.key?(:template)
|
||||
find(options[:template], options[:_prefix])
|
||||
end
|
||||
end
|
||||
|
||||
def _find_layout(layout)
|
||||
@ -102,8 +112,6 @@ def _find_layout(layout)
|
||||
end
|
||||
|
||||
def _render_template(template, layout = nil, options = {})
|
||||
self.formats = template.details[:formats]
|
||||
|
||||
locals = options[:locals] || {}
|
||||
layout = _find_layout(layout) if layout
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
module ActionView #:nodoc:
|
||||
class Template
|
||||
class Text < String #:nodoc:
|
||||
HTML = Mime[:html]
|
||||
|
||||
def initialize(string, content_type = HTML)
|
||||
def initialize(string, content_type = nil)
|
||||
super(string.to_s)
|
||||
@content_type = Mime[content_type] || content_type
|
||||
@content_type = Mime[content_type] || content_type if content_type
|
||||
@content_type ||= Mime::TEXT
|
||||
end
|
||||
|
||||
def details
|
||||
|
@ -59,11 +59,11 @@ def naked_render
|
||||
end
|
||||
|
||||
def rendering_to_body
|
||||
self.response_body = render_to_body :_template_name => "naked_render.erb"
|
||||
self.response_body = render_to_body :template => "naked_render.erb"
|
||||
end
|
||||
|
||||
def rendering_to_string
|
||||
self.response_body = render_to_string :_template_name => "naked_render.erb"
|
||||
self.response_body = render_to_string :template => "naked_render.erb"
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user