Skip to content

Add multi-key caching support for collection blocks #111

@dasch

Description

@dasch

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions