aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
Diffstat (limited to 'actionview')
-rw-r--r--actionview/CHANGELOG.md2
-rw-r--r--actionview/lib/action_view/digestor.rb18
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb7
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb28
-rw-r--r--actionview/lib/action_view/tasks/dependencies.rake4
-rw-r--r--actionview/test/template/digestor_test.rb4
6 files changed, 33 insertions, 30 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 256b90784a..bebe78c360 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -68,7 +68,7 @@
*Vasiliy Ermolovich*
-* Add a `hidden_field` on the `collection_radio_buttons` to avoid raising a error
+* Add a `hidden_field` on the `collection_radio_buttons` to avoid raising an error
when the only input on the form is the `collection_radio_buttons`.
*Mauro George*
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index 359b2f810c..657026fa14 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -22,23 +22,23 @@ module ActionView
# * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
# * <tt>dependencies</tt> - An array of dependent views
# * <tt>partial</tt> - Specifies whether the template is a partial
- def digest(options)
- options.assert_valid_keys(:name, :finder, :dependencies, :partial)
+ def digest(name:, finder:, **options)
+ options.assert_valid_keys(:dependencies, :partial)
- cache_key = ([ options[:name], options[:finder].details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
+ cache_key = ([ name, finder.details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
# this is a correctly done double-checked locking idiom
# (Concurrent::Map's lookups have volatile semantics)
@@cache[cache_key] || @@digest_monitor.synchronize do
@@cache.fetch(cache_key) do # re-check under lock
- compute_and_store_digest(cache_key, options)
+ compute_and_store_digest(cache_key, name, finder, options)
end
end
end
private
- def compute_and_store_digest(cache_key, options) # called under @@digest_monitor lock
- klass = if options[:partial] || options[:name].include?("/_")
+ def compute_and_store_digest(cache_key, name, finder, options) # called under @@digest_monitor lock
+ klass = if options[:partial] || name.include?("/_")
# Prevent re-entry or else recursive templates will blow the stack.
# There is no need to worry about other threads seeing the +false+ value,
# as they will then have to wait for this thread to let go of the @@digest_monitor lock.
@@ -48,7 +48,7 @@ module ActionView
Digestor
end
- @@cache[cache_key] = stored_digest = klass.new(options).digest
+ @@cache[cache_key] = stored_digest = klass.new(name, finder, options).digest
ensure
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
@@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
@@ -57,7 +57,7 @@ module ActionView
attr_reader :name, :finder, :options
- def initialize(name:, finder:, **options)
+ def initialize(name, finder, options = {})
@name, @finder = name, finder
@options = options
end
@@ -80,7 +80,7 @@ module ActionView
def nested_dependencies
dependencies.collect do |dependency|
- dependencies = PartialDigestor.new(name: dependency, finder: finder).nested_dependencies
+ dependencies = PartialDigestor.new(dependency, finder).nested_dependencies
dependencies.any? ? { dependency => dependencies } : dependency
end
end
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index bdbf03191a..a9bd257e76 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -428,6 +428,8 @@ module ActionView
layout = find_template(layout, @template_keys)
end
+ collection_cache_eligible = automatic_cache_eligible?
+
partial_iteration = PartialIteration.new(@collection.size)
locals[iteration] = partial_iteration
@@ -436,6 +438,11 @@ module ActionView
locals[counter] = partial_iteration.index
content = template.render(view, locals)
+
+ if collection_cache_eligible
+ collection_cache_rendered_partial(content, object)
+ end
+
content = layout.render(view, locals) { content } if layout
partial_iteration.iterate!
content
diff --git a/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb b/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb
index c353eb0b31..4860f00243 100644
--- a/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb
@@ -15,13 +15,16 @@ module ActionView
return yield unless cache_collection?
keyed_collection = collection_by_cache_keys
- partial_cache = collection_cache.read_multi(*keyed_collection.keys)
+ cached_partials = collection_cache.read_multi(*keyed_collection.keys)
- @collection = keyed_collection.reject { |key, _| partial_cache.key?(key) }.values
- rendered_partials = @collection.any? ? yield.dup : []
+ @collection = keyed_collection.reject { |key, _| cached_partials.key?(key) }.values
+ rendered_partials = @collection.empty? ? [] : yield
- fetch_or_cache_partial(partial_cache, order_by: keyed_collection.each_key) do
- rendered_partials.shift
+ index = 0
+ keyed_collection.map do |cache_key, _|
+ cached_partials.fetch(cache_key) do
+ rendered_partials[index].tap { index += 1 }
+ end
end
end
@@ -50,17 +53,10 @@ module ActionView
key.frozen? ? key.dup : key # #read_multi & #write may require mutability, Dalli 2.6.0.
end
- def fetch_or_cache_partial(cached_partials, order_by:)
- rely_on_individual_cache_call = !callable_cache_key?
-
- order_by.map do |key|
- cached_partials.fetch(key) do
- yield.tap do |rendered_partial|
- unless rely_on_individual_cache_call
- collection_cache.write(key, rendered_partial, @options[:cache_options])
- end
- end
- end
+ def collection_cache_rendered_partial(rendered_partial, key_by)
+ if callable_cache_key?
+ key = expanded_cache_key(@options[:cache].call(key_by))
+ collection_cache.write(key, rendered_partial, @options[:cache_options])
end
end
end
diff --git a/actionview/lib/action_view/tasks/dependencies.rake b/actionview/lib/action_view/tasks/dependencies.rake
index f394c319c1..9932ff8b6d 100644
--- a/actionview/lib/action_view/tasks/dependencies.rake
+++ b/actionview/lib/action_view/tasks/dependencies.rake
@@ -2,13 +2,13 @@ namespace :cache_digests do
desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
task :nested_dependencies => :environment do
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).nested_dependencies
+ puts JSON.pretty_generate ActionView::Digestor.new(CacheDigests.template_name, CacheDigests.finder).nested_dependencies
end
desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
task :dependencies => :environment do
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).dependencies
+ puts JSON.pretty_generate ActionView::Digestor.new(CacheDigests.template_name, CacheDigests.finder).dependencies
end
class CacheDigests
diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb
index ea86535b2a..bfab97cf1e 100644
--- a/actionview/test/template/digestor_test.rb
+++ b/actionview/test/template/digestor_test.rb
@@ -308,11 +308,11 @@ class TemplateDigestorTest < ActionView::TestCase
end
def dependencies(template_name)
- ActionView::Digestor.new({ name: template_name, finder: finder }).dependencies
+ ActionView::Digestor.new(template_name, finder).dependencies
end
def nested_dependencies(template_name)
- ActionView::Digestor.new({ name: template_name, finder: finder }).nested_dependencies
+ ActionView::Digestor.new(template_name, finder).nested_dependencies
end
def finder