Search code examples
ruby-on-railscachingruby-on-rails-4memcachedcache-digests

Disable cache digests in Rails 4


I'm in the process of migrating a Rails 3 app to Rails 4. The migration was mostly fairly smooth, but one big problem I'm encountering is that my old Rails 3 code to expire my caches isn't working. I'm getting logs like:

Expire fragment views/localhost:3000/cardsets/36?action_suffix=edityes (0.0ms)
...
Read fragment   views/localhost:3000/cardsets/36?action_suffix=edityes/d8034b6e68ba30b5916a2ebb73b68ffe (0.0ms)

This turns out to be because Rails 4 brings a new funky kind of caching, cache digests. That long string of hex on the end is the md5 digest of some view that Rails wants to associate with this cache fragment.

I believe I have no need for cache digests. My application gets updated pretty infrequently, and generally I can clear the cache when it's updated, so the concept of a cache fragment that refers to a previous deployment's version of a piece of my view code is irrelevant.

I see that I can modify any given call to cache with the :skip_digest => true flag. This blog post refers to modifying a large number of their cache calls to add :skip_digest. But I believe I want to apply this flag to every single call to cache in my application. Surely there must be some way to just disable cache digests universally?


Solution

  • Easiest way to do this is to monkey patch the cache_fragment_name method so that skip_digest is true by default. In order to use the md5 digest when you need it, you'd just need to set skip_digest to false

    module ActionView
      module Helpers
        module CacheHelper
          def cache_fragment_name(name = {}, options = nil)
            skip_digest = options && !options[:skip_digest].nil? ? options[:skip_digest] : true
    
            if skip_digest
              name
            else
              fragment_name_with_digest(name)
            end
          end
        end
      end
    end