[Skip To Content]


# dead_good_caching

Say you have some pages which are publicly accessible, but have some admin-only links on them when someone is logged into the site. Also, let’s pretend that you’re going to be Slashdotted any day now, and you want to cache the pages, and you quite fancy using Rails’ page caching because it’s nice and easy to use.

“But”, I hear you cry, “if you use caches_page in your controller, it’ll cache the page regardless! You’ll cache your admin links! Everyone will be able to see that you have ajaxy editing on your blog!”

NO! NOT ANY MORE! As of this afternoon, that’s not the case! Read on!

Stick this in lib/dead_good_caching.rb :

  1. module ActionController
  2. module Caching
  3. module Pages
  4. module ClassMethods
  5. alias_method :rubbish_caches_page, :caches_page
  6. def caches_page( *actions )
  7. return unless perform_caching
  8. if_proc = actions.last.is_a?( Hash ) ? actions.pop[ :if ] : nil
  9. actions.each do |action|
  10. class_eval "after_filter { |c| c.cache_page if c.action_name == '#{action}' and ( not if_proc or ( if_proc and if_proc.call( c ) ) ) }"
  11. end
  12. end
  13. end
  14. end
  15. end
  16. end

Then, in your config/environment.rb file, somewhere near the bottom :

  1. require 'dead_good_caching'

Then, in your controllers, you can do something like :

  1. caches_page :list, :tag, :show, :if => Proc.new { |controller|
  2. not controller.logged_in?
  3. }

The above won’t cache your last, tag and show actions if you’re logged in! Good eh? If don’t want to do any checking, you can still use caches_page as God^WDHH intended.

“But”, I hear you cry louder, “if a non-logged in user visits the page, Rails will write it out to disk, and because you’ve configured Apache to not bother Rails if a file exists on disk, you, as an admin, will get served that cached page!”

Ah ha! I have to admit, it took a few minutes to figure out a workaround for this. But, assuming you have the ability to mod_rewrite on your server and that the cookie’s name which is set when you login is your_cool_cookie_name, you just need to add something like :

  1. RewriteRule ^/$ /index [QSA]
  2. RewriteCond %{HTTP_COOKIE} !(your_cool_cookie_name=(.*?))
  3. RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.html -f
  4. RewriteRule ^(.*)$ $1.html [QSA,L]

to your vhost or .htaccess and you’ll be set. Unless I’ve messed up the rules, which I may have done.

As (almost) always, the above code is public domain.

(Update : My procrastination has led to someone else submitting a patch for Rails Core and getting it accepted. See here and here. The upshot is that in Rails 2.1, you won’t need the above hack.)

More about this site...

Last Week’s Top 5 Albums (More »)

  1. Field RecordingsBell X1
  2. Hurry Up, We're DreamingM83
  3. Dance the DevilThe Frames
  4. TorchesFoster the People
  5. Burn the MapsThe Frames