Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up partial rendering by caching "variable" calculation #35171

Merged
merged 1 commit into from
Feb 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 31 additions & 18 deletions actionview/lib/action_view/renderer/partial_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,21 @@ def initialize(*)
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.first
Expand Down Expand Up @@ -359,7 +372,7 @@ def render_partial(view, template)
# 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)
def setup(context, options, as, block)
@options = options
@block = block

Expand All @@ -382,25 +395,25 @@ def setup(context, options, block)

if @collection
paths = @collection_data = @collection.map { |o| partial_path(o, context) }
@path = paths.uniq.one? ? paths.first : nil
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(@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
Expand All @@ -414,8 +427,8 @@ def collection_from_object
@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)
Expand Down Expand Up @@ -511,9 +524,9 @@ def merge_prefix_into_object_path(prefix, object_path)
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
Expand Down
9 changes: 9 additions & 0 deletions actionview/lib/action_view/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class Template
end
end

attr_reader :variable

def initialize(source, identifier, handler, details)
format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))

Expand All @@ -138,6 +140,13 @@ def initialize(source, identifier, handler, details)
@original_encoding = nil
@locals = details[:locals] || []
@virtual_path = details[:virtual_path]

@variable = if @virtual_path
base = @virtual_path[-1] == "/" ? "" : File.basename(@virtual_path)
base =~ /\A_?(.*?)(?:\.\w+)*\z/
$1.to_sym
end

@updated_at = details[:updated_at] || Time.now
@formats = Array(format).map { |f| f.respond_to?(:ref) ? f.ref : f }
@variants = [details[:variant]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module ActiveRecord
module Railties # :nodoc:
module CollectionCacheAssociationLoading #:nodoc:
def setup(context, options, block)
def setup(context, options, as, block)
@relation = relation_from_options(options)

super
Expand Down