aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@github.com>2019-02-05 16:41:43 -0800
committerGitHub <noreply@github.com>2019-02-05 16:41:43 -0800
commit9483cdee0a3ed9c686e338f079b0e369597b1211 (patch)
tree09b312964b87fb8237e45e7e6bd1703e9f0bafcc /actionview
parent8d06c108c7af1e9a5db9f6d3c79fc5584cc3784e (diff)
parent24b068bea13e8f91397b3440494f0a5326f80882 (diff)
downloadrails-9483cdee0a3ed9c686e338f079b0e369597b1211.tar.gz
rails-9483cdee0a3ed9c686e338f079b0e369597b1211.tar.bz2
rails-9483cdee0a3ed9c686e338f079b0e369597b1211.zip
Merge pull request #35171 from rails/speed-up-partials
Speed up partial rendering by caching "variable" calculation
Diffstat (limited to 'actionview')
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb49
-rw-r--r--actionview/lib/action_view/template.rb9
2 files changed, 40 insertions, 18 deletions
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index 478400e016..801916954f 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -295,8 +295,21 @@ 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.first
@@ -359,7 +372,7 @@ 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)
+ def setup(context, options, as, block)
@options = options
@block = block
@@ -382,25 +395,25 @@ module ActionView
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
@@ -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)
@@ -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
diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb
index 3b2c264ed4..8a5407c622 100644
--- a/actionview/lib/action_view/template.rb
+++ b/actionview/lib/action_view/template.rb
@@ -128,6 +128,8 @@ module ActionView
end
end
+ attr_reader :variable
+
def initialize(source, identifier, handler, details)
format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
@@ -138,6 +140,13 @@ module ActionView
@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]]