aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/renderer/partial_renderer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionview/lib/action_view/renderer/partial_renderer.rb')
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb97
1 files changed, 55 insertions, 42 deletions
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index cb850d75ee..801916954f 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -295,43 +295,57 @@ module ActionView
end
def render(context, options, block)
- setup(context, options, block)
- @template = find_partial
+ as = as_variable(options)
+ setup(context, options, as, block)
+
+ if @path
+ if @has_object || @collection
+ @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
+ @template_keys = retrieve_template_keys(@variable)
+ else
+ @template_keys = @locals.keys
+ end
+ template = find_partial(@path, @template_keys)
+ @variable ||= template.variable
+ else
+ template = nil
+ end
@lookup_context.rendered_format ||= begin
- if @template && @template.formats.present?
- @template.formats.first
+ if template && template.formats.first
+ template.formats.first
else
formats.first
end
end
if @collection
- render_collection
+ render_collection(context, template)
else
- render_partial
+ render_partial(context, template)
end
end
private
- def render_collection
- instrument(:collection, count: @collection.size) do |payload|
+ def render_collection(view, template)
+ identifier = (template && template.identifier) || @path
+ instrument(:collection, identifier: identifier, count: @collection.size) do |payload|
return nil if @collection.blank?
if @options.key?(:spacer_template)
- spacer = find_template(@options[:spacer_template], @locals.keys).render(@view, @locals)
+ spacer = find_template(@options[:spacer_template], @locals.keys).render(view, @locals)
end
- cache_collection_render(payload) do
- @template ? collection_with_template : collection_without_template
+ cache_collection_render(payload, view, template) do
+ template ? collection_with_template(view, template) : collection_without_template(view)
end.join(spacer).html_safe
end
end
- def render_partial
- instrument(:partial) do |payload|
- view, locals, block = @view, @locals, @block
+ def render_partial(view, template)
+ instrument(:partial, identifier: template.identifier) do |payload|
+ locals, block = @locals, @block
object, as = @object, @variable
if !block && (layout = @options[:layout])
@@ -341,12 +355,12 @@ module ActionView
object = locals[as] if object.nil? # Respect object when object is false
locals[as] = object if @has_object
- content = @template.render(view, locals) do |*name|
+ content = template.render(view, locals) do |*name|
view._layout_for(*name, &block)
end
content = layout.render(view, locals) { content } if layout
- payload[:cache_hit] = view.view_renderer.cache_hits[@template.virtual_path]
+ payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
content
end
end
@@ -358,12 +372,11 @@ module ActionView
# If +options[:partial]+ is a string, then the <tt>@path</tt> instance variable is
# set to that string. Otherwise, the +options[:partial]+ object must
# respond to +to_partial_path+ in order to setup the path.
- def setup(context, options, block)
- @view = context
+ def setup(context, options, as, block)
@options = options
@block = block
- @locals = options[:locals] ? options[:locals].symbolize_keys : {}
+ @locals = options[:locals] || {}
@details = extract_details(options)
prepend_formats(options[:formats])
@@ -381,26 +394,26 @@ module ActionView
@collection = collection_from_object || collection_from_options
if @collection
- paths = @collection_data = @collection.map { |o| partial_path(o) }
- @path = paths.uniq.one? ? paths.first : nil
+ paths = @collection_data = @collection.map { |o| partial_path(o, context) }
+ if paths.uniq.length == 1
+ @path = paths.first
+ else
+ paths.map! { |path| retrieve_variable(path, as).unshift(path) }
+ @path = nil
+ end
else
- @path = partial_path
+ @path = partial_path(@object, context)
end
end
+ self
+ end
+
+ def as_variable(options)
if as = options[:as]
raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
- as = as.to_sym
+ as.to_sym
end
-
- if @path
- @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
- @template_keys = retrieve_template_keys
- else
- paths.map! { |path| retrieve_variable(path, as).unshift(path) }
- end
-
- self
end
def collection_from_options
@@ -414,8 +427,8 @@ module ActionView
@object.to_ary if @object.respond_to?(:to_ary)
end
- def find_partial
- find_template(@path, @template_keys) if @path
+ def find_partial(path, template_keys)
+ find_template(path, template_keys)
end
def find_template(path, locals)
@@ -423,8 +436,8 @@ module ActionView
@lookup_context.find_template(path, prefixes, true, locals, @details)
end
- def collection_with_template
- view, locals, template = @view, @locals, @template
+ def collection_with_template(view, template)
+ locals = @locals
as, counter, iteration = @variable, @variable_counter, @variable_iteration
if layout = @options[:layout]
@@ -445,8 +458,8 @@ module ActionView
end
end
- def collection_without_template
- view, locals, collection_data = @view, @locals, @collection_data
+ def collection_without_template(view)
+ locals, collection_data = @locals, @collection_data
cache = {}
keys = @locals.keys
@@ -474,7 +487,7 @@ module ActionView
#
# If +prefix_partial_path_with_controller_namespace+ is true, then this
# method will prefix the partial paths with a namespace.
- def partial_path(object = @object)
+ def partial_path(object, view)
object = object.to_model if object.respond_to?(:to_model)
path = if object.respond_to?(:to_partial_path)
@@ -483,7 +496,7 @@ module ActionView
raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
end
- if @view.prefix_partial_path_with_controller_namespace
+ if view.prefix_partial_path_with_controller_namespace
prefixed_partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
else
path
@@ -511,9 +524,9 @@ module ActionView
end
end
- def retrieve_template_keys
+ def retrieve_template_keys(variable)
keys = @locals.keys
- keys << @variable if @has_object || @collection
+ keys << variable
if @collection
keys << @variable_counter
keys << @variable_iteration