curly icon indicating copy to clipboard operation
curly copied to clipboard

Add multi-key caching support for collection blocks

Open dasch opened this issue 11 years ago • 0 comments

Since Curly has much more control of rendering when it takes place in a collection block, it should be possible to add smarter caching.

Given the template:

{{*comments}}
  {{body}}
{{/comments}}

... and presenter

class CommentPresenter < Curly::Presenter
  presents :comment

  def body
    @comment.body
  end

  def cache_key
    @comment
  end
end

... we should be able to generate Ruby that looks like this:

class Curly::RenderingContext
  attr_reader :presenter, :value

  def initialize(presenter, value)
    @presenter, @value = presenter, value
  end

  def cache_key
    @presenter.cache_key
  end
end

contexts = presenter.comments.map {|value|
  presenter = find_presenter_for(value) # pseudo code
  Curly::RenderingContext.new(presenter, value)
}

# `fetch_multi` does a multi-get to the cache backend, so the cached fragments
# will be fetched in parallel. It gets the cache key for each item by calling `cache_key`
# on the object. Any object that was not found in the cache will be yielded, and the
# block's return value will be saved in the cache.
Rails.cache.fetch_multi(*contexts) do |context|
  presenter = context.presenter
  # code goes here.
end

That way, if the template is rendered with Comment records A and B, the nested template will be rendered for each and the results stored in the cache. The next time, there's a new Comment record C, so we'll have to render A, B, and C, but A and B are already stored in the cache. We'll do a single GET to the backend, get the pre-rendered HTML for both A and B and a miss for C, so we'll render the nested template with C.

dasch avatar Nov 05 '14 14:11 dasch