» tagged pages
» logout
Ruby
Return to Code Snippets: ruby

Automatic Expiration of Rails Action Caching

Tags Applied to this Entry

1 person has tagged this page:
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 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 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
Username:
Password:
(or Cancel)