Partial cache expiration

315 Views Asked by At

In my Rails app I use regular fragment caching like this:

- cache "books", skip_digest: true do
  - @books.each do |book|
    = book.title
    = book.author

To manage the cache expiration, I use a sweeper:

class BookSweeper < ActionController::Caching::Sweeper
  observe Book

  def after_update(book)
    expire_fragment "books"
  end    
end

Let's say I have 100 books and 1 book is deleted or changed. Then the books cache will expire and the first site visitor will experience a slower page, because a new cache has to be created.

Is there a way to update the cache for only that single book instead of expiring the whole cache for 99 unchanged books? Or is it just all or nothing?

2

There are 2 best solutions below

0
On BEST ANSWER

It is no longer necessary to manually expire your caches - Rails now automatically implements key-based expiration. Thus, you can easily create a unique cache for each book like so:

- @books.each do |book|
  - cache book, skip_digest: true do
    = book.title
    = book.author

This should automatically create and expire each cache for you. No need for any sort of sweeper method.

0
On

From the Guides

You can also use an Active Record model as the cache key:

<% Product.all.each do |p| %>
  <% cache(p) do %>
    <%= link_to p.name, product_url(p) %>
  <% end %>
<% end %>

Try this approach in your case something like this

- @books.each do |book|
   - cache "book", skip_digest: true do
    = book.title
    = book.author

And change after_update(book) method like this

def after_update(book)
   expire_fragment "book"
end

Not sure though, just giving an idea.