提交 cf5bc0dd 编写于 作者: K Kasper Timm Hansen 提交者: GitHub

Merge pull request #25616 from ignatiusreza/callable_cache_key

Bring back support for callable cache key when rendering collection
......@@ -393,9 +393,14 @@ def index_with_comment
@customers = [Customer.new('david', 1)]
render partial: 'customers/commented_customer', collection: @customers, as: :customer, cached: true
end
def index_with_callable_cache_key
@customers = [Customer.new('david', 1)]
render partial: 'customers/customer', collection: @customers, cached: -> customer { 'cached_david' }
end
end
class AutomaticCollectionCacheTest < ActionController::TestCase
class CollectionCacheTest < ActionController::TestCase
def setup
super
@controller = CollectionCacheController.new
......@@ -438,6 +443,11 @@ def test_caching_works_with_beginning_comment
assert_equal 1, @controller.partial_rendered_times
end
def test_caching_with_callable_cache_key
get :index_with_callable_cache_key
assert_customer_cached 'cached_david', 'david, 1'
end
private
def assert_customer_cached(key, content)
assert_match content,
......
......@@ -130,9 +130,10 @@ module CacheHelper
#
# When rendering a collection of objects that each use the same partial, a `cached`
# option can be passed.
#
# For collections rendered such:
#
# <%= render partial: 'notifications/notification', collection: @notifications, cached: true %>
# <%= render partial: 'projects/project', collection: @projects, cached: true %>
#
# The `cached: true` will make Action View's rendering read several templates
# from cache at once instead of one call per template.
......@@ -142,13 +143,21 @@ module CacheHelper
# Works great alongside individual template fragment caching.
# For instance if the template the collection renders is cached like:
#
# # notifications/_notification.html.erb
# <% cache notification do %>
# # projects/_project.html.erb
# <% cache project do %>
# <%# ... %>
# <% end %>
#
# Any collection renders will find those cached templates when attempting
# to read multiple templates at once.
#
# If your collection cache depends on multiple sources (try to avoid this to keep things simple),
# you can name all these dependencies as part of a block that returns an array:
#
# <%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %>
#
# This will include both records as part of the cache key and updating either of them will
# expire the cache.
def cache(name = {}, options = {}, &block)
if controller.respond_to?(:perform_caching) && controller.perform_caching
name_options = options.slice(:skip_digest, :virtual_path)
......
......@@ -25,9 +25,15 @@ def cache_collection_render(instrumentation_payload)
end
end
def callable_cache_key?
@options[:cached].respond_to?(:call)
end
def collection_by_cache_keys
seed = callable_cache_key? ? @options[:cached] : ->(i) { i }
@collection.each_with_object({}) do |item, hash|
hash[expanded_cache_key(item)] = item
hash[expanded_cache_key(seed.call(item))] = item
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册