aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/renderer/template_renderer.rb
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2010-10-10 12:34:31 +0200
committerJosé Valim <jose.valim@gmail.com>2010-10-10 12:43:26 +0200
commit940b57789fb9166658974c591e68d22ecab29f34 (patch)
treeffaf3b57cc89663f5e48a7fc5567dcb510fa931e /actionpack/lib/action_view/renderer/template_renderer.rb
parentb88f4ca93bcaef9a6bfd21d95acc8f432a3c8e5c (diff)
downloadrails-940b57789fb9166658974c591e68d22ecab29f34.tar.gz
rails-940b57789fb9166658974c591e68d22ecab29f34.tar.bz2
rails-940b57789fb9166658974c591e68d22ecab29f34.zip
Add support to render :once.
This will be used internally by sprockets to ensure requires are executed just once.
Diffstat (limited to 'actionpack/lib/action_view/renderer/template_renderer.rb')
-rw-r--r--actionpack/lib/action_view/renderer/template_renderer.rb67
1 files changed, 49 insertions, 18 deletions
diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb
index 3acc68dcac..9f9df15347 100644
--- a/actionpack/lib/action_view/renderer/template_renderer.rb
+++ b/actionpack/lib/action_view/renderer/template_renderer.rb
@@ -1,26 +1,51 @@
+require 'set'
+require 'active_support/core_ext/object/try'
+require 'active_support/core_ext/array/wrap'
require 'action_view/renderer/abstract_renderer'
module ActionView
class TemplateRenderer < AbstractRenderer #:nodoc:
+ attr_reader :rendered
+
+ def initialize(view)
+ super
+ @rendered = Set.new
+ end
+
def render(options)
wrap_formats(options[:template] || options[:file]) do
template = determine_template(options)
- lookup_context.freeze_formats(template.formats, true)
- render_template(template, options[:layout], options)
+ render_template(template, options[:layout], options[:locals])
+ end
+ end
+
+ def render_once(options)
+ paths, locals = options[:once], options[:locals] || {}
+ layout, keys, prefix = options[:layout], locals.keys, options[:prefix]
+
+ raise "render :once expects a String or an Array to be given" unless paths
+
+ render_with_layout(layout, locals) do
+ contents = []
+ Array.wrap(paths).each do |path|
+ template = find_template(path, prefix, false, keys)
+ contents << render_template(template, nil, locals) if @rendered.add?(template)
+ end
+ contents.join("\n")
end
end
# Determine the template to be rendered using the given options.
def determine_template(options) #:nodoc:
- keys = (options[:locals] ||= {}).keys
+ keys = options[:locals].try(:keys) || []
- if options.key?(:inline)
- handler = Template.handler_class_for_extension(options[:type] || "erb")
- Template.new(options[:inline], "inline template", handler, { :locals => keys })
- elsif options.key?(:text)
+ if options.key?(:text)
Template::Text.new(options[:text], formats.try(:first))
elsif options.key?(:file)
with_fallbacks { find_template(options[:file], options[:prefix], false, keys) }
+ elsif options.key?(:inline)
+ handler = Template.handler_class_for_extension(options[:type] || "erb")
+ Template.new(options[:inline], "inline template", handler, { :locals => keys })
elsif options.key?(:template)
options[:template].respond_to?(:render) ?
options[:template] : find_template(options[:template], options[:prefix], false, keys)
@@ -29,20 +54,26 @@ module ActionView
# Renders the given template. An string representing the layout can be
# supplied as well.
- def render_template(template, layout = nil, options = {}) #:nodoc:
- view, locals = @view, options[:locals] || {}
- layout = find_layout(layout, locals.keys) if layout
+ def render_template(template, layout_name = nil, locals = {}) #:nodoc:
+ lookup_context.freeze_formats(template.formats, true)
+ view, locals = @view, locals || {}
- ActiveSupport::Notifications.instrument("render_template.action_view",
- :identifier => template.identifier, :layout => layout.try(:virtual_path)) do
-
- content = template.render(view, locals) { |*name| view._layout_for(*name) }
-
- if layout
- view.store_content_for(:layout, content)
- content = render_layout(layout, locals)
+ render_with_layout(layout_name, locals) do |layout|
+ instrument(:template, :identifier => template.identifier, :layout => layout.try(:virtual_path)) do
+ template.render(view, locals) { |*name| view._layout_for(*name) }
end
+ end
+ end
+
+ def render_with_layout(path, locals) #:nodoc:
+ layout = path && find_layout(path, locals.keys)
+ content = yield(layout)
+ if layout
+ view = @view
+ view.store_content_for(:layout, content)
+ layout.render(view, locals){ |*name| view._layout_for(*name) }
+ else
content
end
end