diff options
author | Aaron Patterson <tenderlove@github.com> | 2019-02-05 16:41:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-05 16:41:43 -0800 |
commit | 9483cdee0a3ed9c686e338f079b0e369597b1211 (patch) | |
tree | 09b312964b87fb8237e45e7e6bd1703e9f0bafcc | |
parent | 8d06c108c7af1e9a5db9f6d3c79fc5584cc3784e (diff) | |
parent | 24b068bea13e8f91397b3440494f0a5326f80882 (diff) | |
download | rails-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
3 files changed, 41 insertions, 19 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]] diff --git a/activerecord/lib/active_record/railties/collection_cache_association_loading.rb b/activerecord/lib/active_record/railties/collection_cache_association_loading.rb index dfaac4eefb..d57680aaaa 100644 --- a/activerecord/lib/active_record/railties/collection_cache_association_loading.rb +++ b/activerecord/lib/active_record/railties/collection_cache_association_loading.rb @@ -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 |