ruby-on-rails-4cachingfragment-caching

Rails 4 Fragment Cache Entire Page. How to Expire Cache In Model


How do I expire the main-page fragment in a model?

In my HTML

<% cache 'main-page' do %>
  # html here
<% end %>

In my Post Model

after_create :clear_cache
after_update :clear_cache

def clear_cache
  ActionController::Base.new.expire_fragment('main-page')
end

This doesn't clear the cache. If I create or update a post, the cache doesn't clear. If I run ActionController::Base.new.expire_fragment('main-page') in rails console it returns 'nil'. If I run Rails.cache.clear instead of ActionController::Base.new.expire_fragment('main-page') in the post model, it works.


Solution

  • I believe your issue is the digest, so if you change your cache to this it should work:

    <% cache 'main-page', skip_digest: true do %>
      # html here
    <% end %>
    

    If you want to use this kind of style, where the cache doesn't expire and relies on detecting model changes to invalidate, you may want to consider using an Observer or Sweeper, which were removed from Rails 4, but are useful for this pattern:

    https://github.com/rails/rails-observers

    Not the answer you are looking for perhaps, but another way:

    Make the cache key based on the max updated_at from the Post model.

    Whenever any post changes, the cache key will automatically miss and go retrieve the latest posts to re-cache that part of the view.

    module HomeHelper
      def cache_key_for_posts
        count          = Post.count
        max_updated_at = Post.maximum(:updated_at).try(:utc).try(:to_s, :number)
        "posts/all-#{count}-#{max_updated_at}"
      end
    end
    

    And then in your view:

    <% cache cache_key_for_posts, skip_digest: true do %>
      # html here
    <% end %>