1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Bring back support for callable cache_key on collection rendering

This commit is contained in:
Ignatius Reza 2016-07-21 08:35:55 +09:00
parent b334c19c07
commit 714c763dad
3 changed files with 30 additions and 5 deletions

View file

@ -393,9 +393,14 @@ class CollectionCacheController < ActionController::Base
@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 @@ class AutomaticCollectionCacheTest < ActionController::TestCase
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,

View file

@ -130,9 +130,10 @@ module ActionView
#
# 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 ActionView
# 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)

View file

@ -25,9 +25,15 @@ module ActionView
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