diff options
author | Richard Schneeman <richard.schneeman+no-recruiters@gmail.com> | 2018-09-20 20:47:04 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-20 20:47:04 -0500 |
commit | a6ff4e856dffcd3324390556ceb899aa6594ceda (patch) | |
tree | 0d04d6e6d0651905bedcc1cc44bfb7af31757cfe | |
parent | a44b7f180d0f03613479fb227d09ce2d7f74a187 (diff) | |
parent | e8283dabd2cdc854b2e8578b597081d4e593159d (diff) | |
download | rails-a6ff4e856dffcd3324390556ceb899aa6594ceda.tar.gz rails-a6ff4e856dffcd3324390556ceb899aa6594ceda.tar.bz2 rails-a6ff4e856dffcd3324390556ceb899aa6594ceda.zip |
Merge pull request #33922 from schneems/schneems/collection-caching-easier-to-understand
[ci skip] document collection_caching.rb
-rw-r--r-- | actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb | 35 |
1 files changed, 35 insertions, 0 deletions
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 3c10e0452f..5aa6f77902 100644 --- a/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb +++ b/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb @@ -14,15 +14,35 @@ module ActionView def cache_collection_render(instrumentation_payload) return yield unless @options[:cached] + # Result is a hash with the key represents the + # key used for cache lookup and the value is the item + # on which the partial is being rendered keyed_collection = collection_by_cache_keys + + # Pull all partials from cache + # Result is a hash, key matches the entry in + # `keyed_collection` where the cache was retrieved and the + # value is the value that was present in the cache cached_partials = collection_cache.read_multi(*keyed_collection.keys) instrumentation_payload[:cache_hits] = cached_partials.size + # Extract the items for the keys that are not found + # Set the uncached values to instance variable @collection + # which is used by the caller @collection = keyed_collection.reject { |key, _| cached_partials.key?(key) }.values + + # If all elements are already in cache then + # rendered partials will be an empty array + # + # If the cache is missing elements then + # the block will be called against the remaining items + # in the @collection. rendered_partials = @collection.empty? ? [] : yield index = 0 fetch_or_cache_partial(cached_partials, order_by: keyed_collection.each_key) do + # This block is called once + # for every cache miss while preserving order. rendered_partials[index].tap { index += 1 } end end @@ -48,6 +68,21 @@ module ActionView @digest_path ||= @view.digest_path_from_virtual(@template.virtual_path) end + # `order_by` is an enumerable object containing keys of the cache, + # all keys are passed in whether found already or not. + # + # `cached_partials` is a hash. If the value exists + # it represents the rendered partial from the cache + # otherwise `Hash#fetch` will take the value of its block. + # + # This method expects a block that will return the rendered + # partial. An example is to render all results + # for each element that was not found in the cache and store it as an array. + # Order it so that the first empty cache element in `cached_partials` + # corresponds to the first element in `rendered_partials`. + # + # If the partial is not already cached it will also be + # written back to the underlying cache store. def fetch_or_cache_partial(cached_partials, order_by:) order_by.map do |cache_key| cached_partials.fetch(cache_key) do |