aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb13
-rw-r--r--actionpack/lib/abstract_controller/rendering_controller.rb17
-rw-r--r--actionpack/lib/action_controller/metal/rendering_controller.rb48
-rw-r--r--actionpack/lib/action_controller/routing/resources.rb18
-rw-r--r--actionpack/lib/action_controller/routing/route_set.rb29
-rw-r--r--actionpack/lib/action_controller/testing/process.rb2
-rwxr-xr-xactionpack/lib/action_dispatch/http/request.rb36
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb6
-rw-r--r--actionpack/lib/action_view/base.rb29
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb5
-rw-r--r--actionpack/lib/action_view/render/partials.rb133
-rw-r--r--actionpack/lib/action_view/render/rendering.rb79
-rw-r--r--actionpack/lib/action_view/template/handler.rb6
-rw-r--r--actionpack/lib/action_view/template/resolver.rb2
-rw-r--r--actionpack/lib/action_view/template/template.rb28
15 files changed, 239 insertions, 212 deletions
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index ac2154dffc..a8bd2b80e1 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -19,15 +19,20 @@ module AbstractController
end
end
+ def clear_template_caches!
+ @found_layouts.clear if @found_layouts
+ super
+ end
+
def cache_layout(details)
layout = @found_layouts
- values = details.values_at(:formats, :locale)
+ key = Thread.current[:format_locale_key]
# Cache nil
- if layout.key?(values)
- return layout[values]
+ if layout.key?(key)
+ return layout[key]
else
- layout[values] = yield
+ layout[key] = yield
end
end
diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb
index bb7891fbfd..feca1bc4b7 100644
--- a/actionpack/lib/abstract_controller/rendering_controller.rb
+++ b/actionpack/lib/abstract_controller/rendering_controller.rb
@@ -111,12 +111,21 @@ module AbstractController
def _determine_template(options)
name = (options[:_template_name] || action_name).to_s
- options[:_template] ||= view_paths.find(
- name, { :formats => formats }, options[:_prefix], options[:_partial]
- )
+ options[:_template] ||= with_template_cache(name) do
+ view_paths.find(
+ name, { :formats => formats }, options[:_prefix], options[:_partial]
+ )
+ end
+ end
+
+ def with_template_cache(name)
+ yield
end
module ClassMethods
+ def clear_template_caches!
+ end
+
# Append a path to the list of view paths for this controller.
#
# ==== Parameters
@@ -134,6 +143,7 @@ module AbstractController
# the default view path. You may also provide a custom view path
# (see ActionView::ViewPathSet for more information)
def prepend_view_path(path)
+ clear_template_caches!
self.view_paths.unshift(path)
end
@@ -148,6 +158,7 @@ module AbstractController
# paths<ViewPathSet, Object>:: If a ViewPathSet is provided, use that;
# otherwise, process the parameter into a ViewPathSet.
def view_paths=(paths)
+ clear_template_caches!
self._view_paths = paths.is_a?(ActionView::PathSet) ?
paths : ActionView::Base.process_view_paths(paths)
end
diff --git a/actionpack/lib/action_controller/metal/rendering_controller.rb b/actionpack/lib/action_controller/metal/rendering_controller.rb
index 5b1be763ad..4da32ca1b3 100644
--- a/actionpack/lib/action_controller/metal/rendering_controller.rb
+++ b/actionpack/lib/action_controller/metal/rendering_controller.rb
@@ -1,20 +1,56 @@
module ActionController
+ class HashKey
+ @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }
+
+ def self.get(klass, formats, locale)
+ @hash_keys[klass][formats][locale] ||= new(klass, formats, locale)
+ end
+
+ attr_accessor :hash
+ def initialize(klass, formats, locale)
+ @formats, @locale = formats, locale
+ @hash = [formats, locale].hash
+ end
+
+ alias_method :eql?, :equal?
+
+ def inspect
+ "#<HashKey -- formats: #{@formats} locale: #{@locale}>"
+ end
+ end
+
module RenderingController
extend ActiveSupport::Concern
include AbstractController::RenderingController
+ module ClassMethods
+ def clear_template_caches!
+ ActionView::Partials::PartialRenderer::TEMPLATES.clear
+ template_cache.clear
+ super
+ end
+
+ def template_cache
+ @template_cache ||= Hash.new {|h,k| h[k] = {} }
+ end
+ end
+
def process_action(*)
self.formats = request.formats.map {|x| x.to_sym}
+
+ super
+ end
+
+ def _determine_template(*)
super
end
def render(options)
+ Thread.current[:format_locale_key] = HashKey.get(self.class, formats, I18n.locale)
+
super
- self.content_type ||= begin
- mime = options[:_template].mime_type
- formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first)
- end.to_s
+ self.content_type ||= options[:_template].mime_type.to_s
response_body
end
@@ -34,6 +70,10 @@ module ActionController
controller_path
end
+ def with_template_cache(name)
+ self.class.template_cache[Thread.current[:format_locale_key]][name] ||= super
+ end
+
def _determine_template(options)
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first)
diff --git a/actionpack/lib/action_controller/routing/resources.rb b/actionpack/lib/action_controller/routing/resources.rb
index 4862cf7115..06506435a2 100644
--- a/actionpack/lib/action_controller/routing/resources.rb
+++ b/actionpack/lib/action_controller/routing/resources.rb
@@ -531,14 +531,14 @@ module ActionController
with_options :controller => resource.controller do |map|
map_associations(resource, options)
+ if block_given?
+ with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
+ end
+
map_collection_actions(map, resource)
map_default_collection_actions(map, resource)
map_new_actions(map, resource)
map_member_actions(map, resource)
-
- if block_given?
- with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
- end
end
end
@@ -546,16 +546,16 @@ module ActionController
resource = SingletonResource.new(entities, options)
with_options :controller => resource.controller do |map|
- map_collection_actions(map, resource)
- map_new_actions(map, resource)
- map_member_actions(map, resource)
- map_default_singleton_actions(map, resource)
-
map_associations(resource, options)
if block_given?
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
end
+
+ map_collection_actions(map, resource)
+ map_new_actions(map, resource)
+ map_member_actions(map, resource)
+ map_default_singleton_actions(map, resource)
end
end
diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb
index 09f6024d39..a4f54ad662 100644
--- a/actionpack/lib/action_controller/routing/route_set.rb
+++ b/actionpack/lib/action_controller/routing/route_set.rb
@@ -407,22 +407,9 @@ module ActionController
# don't use the recalled keys when determining which routes to check
routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]
- routes[1].each_with_index do |route, index|
+ routes.each_with_index do |route, index|
results = route.__send__(method, options, merged, expire_on)
if results && (!results.is_a?(Array) || results.first)
-
- # Compare results with Rails 3.0 behavior
- if routes[0][index] != route
- routes[0].each do |route2|
- new_results = route2.__send__(method, options, merged, expire_on)
- if new_results && (!new_results.is_a?(Array) || new_results.first)
- ActiveSupport::Deprecation.warn "The URL you generated will use the first matching route in routes.rb rather than the \"best\" match. " +
- "In Rails 3.0 #{new_results} would of been generated instead of #{results}"
- break
- end
- end
- end
-
return results
end
end
@@ -463,10 +450,7 @@ module ActionController
@routes_by_controller ||= Hash.new do |controller_hash, controller|
controller_hash[controller] = Hash.new do |action_hash, action|
action_hash[action] = Hash.new do |key_hash, keys|
- key_hash[keys] = [
- routes_for_controller_and_action_and_keys(controller, action, keys),
- deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
- ]
+ key_hash[keys] = routes_for_controller_and_action_and_keys(controller, action, keys)
end
end
end
@@ -487,15 +471,6 @@ module ActionController
end
end
- def deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
- selected = routes.select do |route|
- route.matches_controller_and_action? controller, action
- end
- selected.sort_by do |route|
- (keys - route.significant_keys).length
- end
- end
-
# Subclasses and plugins may override this method to extract further attributes
# from the request, for use by route conditions and such.
def extract_request_environment(request)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 09b1a59254..6bc7d60d76 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -148,7 +148,7 @@ module ActionController #:nodoc:
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- @request.env['HTTP_ACCEPT'] = [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
returning __send__(request_method, action, parameters, session, flash) do
@request.env.delete 'HTTP_X_REQUESTED_WITH'
@request.env.delete 'HTTP_ACCEPT'
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index b23306af62..bff030f0e4 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -106,16 +106,10 @@ module ActionDispatch
@env["action_dispatch.request.accepts"] ||= begin
header = @env['HTTP_ACCEPT'].to_s.strip
- fallback = xhr? ? Mime::JS : Mime::HTML
-
if header.empty?
- [content_type, fallback, Mime::ALL].compact
+ [content_type]
else
- ret = Mime::Type.parse(header)
- if ret.last == Mime::ALL
- ret.insert(-2, fallback)
- end
- ret
+ Mime::Type.parse(header)
end
end
end
@@ -163,26 +157,20 @@ module ActionDispatch
# GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
#
def format(view_path = [])
- @env["action_dispatch.request.format"] ||=
- if parameters[:format]
- Mime[parameters[:format]]
- elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL)
- accepts.first
- elsif xhr? then Mime::JS
- else Mime::HTML
- end
+ formats.first
end
def formats
- if ActionController::Base.use_accept_header
- if param = parameters[:format]
- Array.wrap(Mime[param])
+ accept = @env['HTTP_ACCEPT']
+
+ @env["action_dispatch.request.formats"] ||=
+ if parameters[:format]
+ [Mime[parameters[:format]]]
+ elsif xhr? || (accept && !accept.include?(?,))
+ accepts
else
- accepts.dup
+ [Mime::HTML]
end
- else
- [format]
- end
end
# Sets the \format by string extension, which can be used to force custom formats
@@ -198,7 +186,7 @@ module ActionDispatch
# end
def format=(extension)
parameters[:format] = extension.to_s
- @env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format])
+ @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
end
# Returns a symbolized version of the <tt>:format</tt> parameter of the request.
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index e83cf9236b..ff2b2fe74b 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -47,6 +47,8 @@ module ActionDispatch
false
end
rescue Exception => e # YAML, XML or Ruby code block errors
+ logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
+
raise
{ "body" => request.raw_post,
"content_type" => request.content_type,
@@ -67,5 +69,9 @@ module ActionDispatch
nil
end
+
+ def logger
+ defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
+ end
end
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c171a5a8f5..ec1b07797b 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -175,6 +175,17 @@ module ActionView #:nodoc:
attr_accessor :controller
attr_internal :captures
+ def reset_formats(formats)
+ @formats = formats
+
+ if defined?(ActionController)
+ # This is expensive, but we need to reset this when the format is updated,
+ # which currently only happens
+ Thread.current[:format_locale_key] =
+ ActionController::HashKey.get(self.class, formats, I18n.locale)
+ end
+ end
+
class << self
delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
delegate :logger, :to => 'ActionController::Base', :allow_nil => true
@@ -240,7 +251,7 @@ module ActionView #:nodoc:
end
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc:
- @formats = formats || [:html]
+ @formats = formats
@assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
@controller = controller
@helpers = self.class.helpers || Module.new
@@ -255,15 +266,6 @@ module ActionView #:nodoc:
@view_paths = self.class.process_view_paths(paths)
end
- def with_template(current_template)
- _evaluate_assigns_and_ivars
- last_template, self.template = template, current_template
- last_formats, self.formats = formats, current_template.formats
- yield
- ensure
- self.template, self.formats = last_template, last_formats
- end
-
def punctuate_body!(part)
flush_output_buffer
response.body_parts << part
@@ -272,18 +274,11 @@ module ActionView #:nodoc:
# Evaluates the local assigns and controller ivars, pushes them to the view.
def _evaluate_assigns_and_ivars #:nodoc:
- @assigns_added ||= _copy_ivars_from_controller
- end
-
- private
-
- def _copy_ivars_from_controller #:nodoc:
if @controller
variables = @controller.instance_variable_names
variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
end
- true
end
end
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 624b537ad2..03f1dabb4e 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -991,12 +991,13 @@ module ActionView
def render(*options_for_render)
old_formats = @context && @context.formats
- @context.formats = [:html] if @context
+
+ @context.reset_formats([:html]) if @context
Hash === options_for_render.first ?
@context.render(*options_for_render) :
options_for_render.first.to_s
ensure
- @context.formats = old_formats if @context
+ @context.reset_formats(old_formats) if @context
end
def javascript_object_for(object)
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index 83175ab4cf..7f10f54d2e 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -173,44 +173,50 @@ module ActionView
extend ActiveSupport::Concern
class PartialRenderer
- def self.partial_names
- @partial_names ||= Hash.new {|h,k| h[k] = ActiveSupport::ConcurrentHash.new }
- end
+ PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} }
+ TEMPLATES = Hash.new {|h,k| h[k] = {} }
- def self.formats
- @formats ||= Hash.new {|h,k| h[k] = Hash.new{|h,k| h[k] = Hash.new {|h,k| h[k] = {}}}}
- end
+ attr_reader :template
def initialize(view_context, options, block)
- partial = options[:partial]
-
- @memo = {}
@view = view_context
- @options = options
- @locals = options[:locals] || {}
- @block = block
-
- # Set up some instance variables to speed up memoizing
- @partial_names = self.class.partial_names[@view.controller.class]
- @templates = self.class.formats
- @format = view_context.formats
-
- # Set up the object and path
- @object = partial.is_a?(String) ? options[:object] : partial
- @path = partial_path(partial)
+ @partial_names = PARTIAL_NAMES[@view.controller.class]
+
+ key = Thread.current[:format_locale_key]
+ @templates = TEMPLATES[key] if key
+
+ setup(options, block)
+ end
+
+ def setup(options, block)
+ partial = options[:partial]
+
+ @options = options
+ @locals = options[:locals] || {}
+ @block = block
+
+ if String === partial
+ @object = options[:object]
+ @path = partial
+ else
+ @object = partial
+ @path = partial_path(partial)
+ end
end
def render
- return render_collection if collection
-
- template = find_template
- render_template(template, @object || @locals[template.variable_name])
+ if @collection = collection
+ render_collection
+ else
+ @template = template = find_template
+ render_template(template, @object || @locals[template.variable_name])
+ end
end
def render_collection
- @options[:_template] = template = find_template
+ @template = template = find_template
- return nil if collection.blank?
+ return nil if @collection.blank?
if @options.key?(:spacer_template)
spacer = find_template(@options[:spacer_template]).render(@view, @locals)
@@ -223,57 +229,58 @@ module ActionView
def collection_with_template(template)
options = @options
- segments, locals, as = [], @locals, options[:as] || :object
+ segments, locals, as = [], @locals, options[:as] || template.variable_name
- variable_name = template.variable_name
counter_name = template.counter_name
locals[counter_name] = -1
- collection.each do |object|
+ @collection.each do |object|
locals[counter_name] += 1
- locals[variable_name] = object
- locals[as] = object if as
+ locals[as] = object
segments << template.render(@view, locals)
end
+
+ @template = template
segments
end
def collection_without_template
options = @options
- segments, locals, as = [], @locals, options[:as] || :object
+ segments, locals, as = [], @locals, options[:as]
index, template = -1, nil
- collection.each do |object|
+ @collection.each do |object|
template = find_template(partial_path(object))
locals[template.counter_name] = (index += 1)
locals[template.variable_name] = object
- locals[as] = object if as
segments << template.render(@view, locals)
end
- @options[:_template] = template
+ @template = template
segments
end
def render_template(template, object = @object)
- @options[:_template] ||= template
+ options, locals, view = @options, @locals, @view
+ locals[options[:as] || template.variable_name] = object
- # TODO: is locals[:object] really necessary?
- @locals[:object] = @locals[template.variable_name] = object
- @locals[@options[:as]] = object if @options[:as]
+ content = template.render(view, locals) do |*name|
+ @view._layout_for(*name, &@block)
+ end
- content = @view._render_single_template(template, @locals, &@block)
- return content if @block || !@options[:layout]
- find_template(@options[:layout]).render(@view, @locals) { content }
+ if @block || !options[:layout]
+ content
+ else
+ find_template(options[:layout]).render(@view, @locals) { content }
+ end
end
-
private
def collection
- @collection ||= if @object.respond_to?(:to_ary)
+ if @object.respond_to?(:to_ary)
@object
elsif @options.key?(:collection)
@options[:collection] || []
@@ -281,15 +288,19 @@ module ActionView
end
def find_template(path = @path)
- return if !path
- @templates[path][@view.controller_path][@format][I18n.locale] ||= begin
- prefix = @view.controller.controller_path unless path.include?(?/)
- @view.find(path, {:formats => @view.formats}, prefix, true)
+ unless @templates
+ path && _find_template(path)
+ else
+ path && @templates[path] ||= _find_template(path)
end
end
+
+ def _find_template(path)
+ prefix = @view.controller.controller_path unless path.include?(?/)
+ @view.find(path, {:formats => @view.formats}, prefix, true)
+ end
def partial_path(object = @object)
- return object if object.is_a?(String)
@partial_names[object.class] ||= begin
return nil unless object.respond_to?(:to_model)
@@ -302,14 +313,26 @@ module ActionView
end
def render_partial(options)
- @assigns_added = false
- # TODO: Handle other details here.
- self.formats = options[:_details][:formats] if options[:_details]
- _render_partial(options)
+ _evaluate_assigns_and_ivars
+
+ details = options[:_details]
+
+ # Is this needed
+ self.formats = details[:formats] if details
+ renderer = PartialRenderer.new(self, options, nil)
+ text = renderer.render
+ options[:_template] = renderer.template
+ text
end
def _render_partial(options, &block) #:nodoc:
- PartialRenderer.new(self, options, block).render
+ if @renderer
+ @renderer.setup(options, block)
+ else
+ @renderer = PartialRenderer.new(self, options, block)
+ end
+
+ @renderer.render
end
end
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index c7afc56e3b..b0b75918b7 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -12,8 +12,6 @@ module ActionView
# as the locals hash.
def render(options = {}, locals = {}, &block) #:nodoc:
case options
- when String, NilClass
- _render_partial(:partial => options, :locals => locals || {})
when Hash
layout = options[:layout]
@@ -35,26 +33,8 @@ module ActionView
end
when :update
update_page(&block)
- end
- end
-
- def _render_content(content, layout, locals)
- return content unless layout
-
- locals ||= {}
-
- if controller && layout
- @_layout = layout.identifier
- logger.info("Rendering template within #{layout.identifier}") if logger
- end
-
- begin
- old_content, @_content_for[:layout] = @_content_for[:layout], content
-
- @cached_content_for_layout = @_content_for[:layout]
- _render_single_template(layout, locals)
- ensure
- @_content_for[:layout] = old_content
+ else
+ _render_partial(:partial => options, :locals => locals)
end
end
@@ -90,48 +70,25 @@ module ActionView
# In this case, the layout would receive the block passed into <tt>render :layout</tt>,
# and the Struct specified in the layout would be passed into the block. The result
# would be <html>Hello David</html>.
- def _layout_for(names, &block)
- with_output_buffer do
- # This is due to the potentially ambiguous use of yield when
- # a block is passed in to a template *and* there is a content_for()
- # of the same name. Suggested solution: require explicit use of content_for
- # in these ambiguous cases.
- #
- # We would be able to continue supporting yield in all non-ambiguous
- # cases. Question: should we deprecate yield in favor of content_for
- # and reserve yield for cases where there is a yield into a real block?
- if @_content_for.key?(names.first) || !block_given?
- return @_content_for[names.first || :layout]
- else
- return yield(names)
- end
- end
- end
+ def _layout_for(name = nil)
+ return @_content_for[name || :layout] if !block_given? || name
- def _render_single_template(template, locals = {}, &block)
- with_template(template) do
- template.render(self, locals) do |*names|
- _layout_for(names, &block)
- end
- end
- rescue Exception => e
- if e.is_a?(TemplateError)
- e.sub_template_of(template)
- raise e
- else
- raise TemplateError.new(template, assigns, e)
+ with_output_buffer do
+ return yield
end
end
def _render_inline(inline, layout, options)
handler = Template.handler_class_for_extension(options[:type] || "erb")
template = Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
- content = _render_single_template(template, options[:locals] || {})
- layout ? _render_content(content, layout, options[:locals]) : content
+ locals = options[:locals] || {}
+ content = template.render(self, locals)
+ content = layout.render(self, locals) {|*name| _layout_for(*name) { content } } if layout
+ content
end
def _render_text(text, layout, options)
- layout ? _render_content(text, layout, options[:locals]) : text
+ text = layout.render(self, options[:locals]) { text } if layout
end
# This is the API to render a ViewContext's template from a controller.
@@ -141,7 +98,7 @@ module ActionView
# _layout:: The layout, if any, to wrap the Template in
# _partial:: true if the template is a partial
def render_template(options)
- @assigns_added = nil
+ _evaluate_assigns_and_ivars
template, layout, partial = options.values_at(:_template, :_layout, :_partial)
_render_template(template, layout, options, partial)
end
@@ -158,10 +115,18 @@ module ActionView
content = if partial
_render_partial_object(template, options)
else
- _render_single_template(template, locals)
+ template.render(self, locals)
end
- _render_content(content, layout, locals)
+ @cached_content_for_layout = content
+ @_content_for[:layout] = content
+
+ if layout
+ @_layout = layout.identifier
+ logger.info("Rendering template within #{layout.identifier}") if logger
+ content = layout.render(self, locals) {|*name| _layout_for(*name) }
+ end
+ content
end
end
end \ No newline at end of file
diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb
index 3071c78174..4bf58b9fa8 100644
--- a/actionpack/lib/action_view/template/handler.rb
+++ b/actionpack/lib/action_view/template/handler.rb
@@ -26,11 +26,7 @@ module ActionView
self.default_format = Mime::HTML
def self.call(template)
- "#{name}.new(self).render(template, local_assigns)"
- end
-
- def initialize(view = nil)
- @view = view
+ raise "Need to implement #{self.class.name}#call(template)"
end
def render(template, local_assigns)
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 10f664736f..fe657166d5 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -42,7 +42,7 @@ module ActionView
def handler_glob
@handler_glob ||= begin
- e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join
+ e = TemplateHandlers.extensions.map{|h| ".#{h}"}.join(",")
"{#{e}}"
end
end
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index 33d3f79ad3..7d6964e3e3 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -26,9 +26,16 @@ module ActionView
@details[:formats] = Array.wrap(format.to_sym)
end
- def render(view, locals, &blk)
+ def render(view, locals, &block)
method_name = compile(locals, view)
- view.send(method_name, locals, &blk)
+ view.send(method_name, locals, &block)
+ rescue Exception => e
+ if e.is_a?(TemplateError)
+ e.sub_template_of(self)
+ raise e
+ else
+ raise TemplateError.new(self, view.assigns, e)
+ end
end
# TODO: Figure out how to abstract this
@@ -90,7 +97,22 @@ module ActionView
raise ActionView::TemplateError.new(self, {}, e)
end
end
-
+
+ class LocalsKey
+ @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }
+
+ def self.get(*locals)
+ @hash_keys[*locals] ||= new(klass, format, locale)
+ end
+
+ attr_accessor :hash
+ def initialize(klass, format, locale)
+ @hash = locals.hash
+ end
+
+ alias_method :eql?, :equal?
+ end
+
def build_method_name(locals)
# TODO: is locals.keys.hash reliably the same?
@method_names[locals.keys.hash] ||=