Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Automatic Expiration of Rails Action Caching (See related posts)

Would love to get some feedback on this...

No doubt, 5 minutes after posting this, someone will tell me of the built-in Rails way of doing this, but alas I could not find it.

Usage looks like this:

class PeopleController < ApplicationController
  caches_action :show, :for => 1.hour, :cache_path => Proc.new { |c| "people/#{c.params[:id]}_for_#{Person.logged_in.id}" }
end


The ":for => 1.hour" part is where the magic happens.

Basically, this bit of code adds a before_filter that checks the last modified time of the cache entry, and expires it if it is older than the specified time period.

module ActionController
  module Caching
    module Fragments
      # expire a cache key only if the block returns true or
      # if the age of the fragment is more than the specified age argument.
      def expire_fragment_by_mtime(key, age=nil, &block)
        block = Proc.new { |m| m < age.ago } unless block_given?
        if (m = cache_store.mtime(fragment_cache_key(key))) and block.call(m)
          expire_fragment(key)
        end
      end
    end
    module Actions
      module ClassMethods
        # adds an option :for
        # caches_action :show, :for => 2.hours, :cache_path => ...
        # :cache_path is required, unfortunately
        def caches_action_with_for(*actions)
          original_actions = actions.clone
          options = actions.extract_options!
          if for_time = options.delete(:for)
            cache_path = options[:cache_path]
            before_filter do |controller|
              cache_path = cache_path.call(controller) if cache_path.respond_to?(:call)
              controller.expire_fragment_by_mtime(cache_path, for_time)
            end
          end
          caches_action_without_for(*original_actions)
        end
        alias_method_chain :caches_action, :for
      end
    end
  end
end

# Add a method to grab the last modified time of the cache key.
# If you use a store other than the FileStore, you'll need to add
# a method like this to your store.
module ActiveSupport
  module Cache
    class FileStore
      def mtime(name)
        File.mtime(real_file_path(name)) rescue nil
      end
    end
  end
end

You need to create an account or log in to post comments to this site.


Click here to browse all 6638 code snippets

Related Posts