Ruby on Rails: gettext + memcache = trouble

posted in: cache, fragment caching, gettext, rails, ruby | 0

The latest Ruby gettext 1.10.0 gem broke the memcache based fragment caching of the current project I’m working on. I figured out what the problem was. gettext 1.10.0 tries to localize caching of fragments by kind of appending the Locale.current to the fragment cache key, e.g. “items/show/1” becomes “items/show/1_en”, “items/show/1_de”, …

This by itself isn’t a problem but gettext also overwrites the default Rails implementation for expiring fragments. The gettext mechanism expires each localized cache fragment for a given key, e.g. “items/show/1_*” (where * is a wildcard). The current memcache-client gem (1.5.0) however doesn’t support wildcard based key access and a “delete_if method not defined” exception gets thrown.

My solution overwrites the fragment cache expiry implementation of gettext and still uses automatic cache key localization. The difference is, that an expired key gets only expired for the current locale. This works pretty good in my current project – but may require some special care if you really want to expire every localized cached fragment. Suggestions are welcome 😉

Well, here’s the code. Simply copy paste it into a file named “fix_gettext_caching.rb” and put it into your applications lib directory. That’s it.

# This "patch" fixes the ActionController::Caching::Fragments "extension"
# of gettext >= 1.10.0

require 'gettext'

module ActionController #:nodoc: all
  module Caching
    module Fragments
      if defined?(:fragment_cache_key_with_gettext)
        
        def fragment_cache_key(name)
          key = fragment_cache_key_without_gettext(name)
          key = "#{Locale.current}/#{key}" if key.is_a?(String)
          key
        end
        
        def expire_fragment(name, options = nil)
          expire_fragment_without_gettext(name, options)
        end
      end
    end
  end
end