jlaine.net

More Rails Goodness

Rails version 0.9.4.1 is out and ohmigod. The framework is going forward so fast I have trouble following up with all the new stuff. Here’s the greatest of the latest: Caching.

Well, yeah, caching is no news as such. It’s the way David implemented it (just like other things) in Rails that can’t stop astounding me. It’s so simple it almost makes me cry. Want to cache some whole pages your controller is serving? Just do this:


  class WeblogController < ActionController::Base
    caches_page :show, :new
  end

Phew, that was all good and well. But what if you have some personalized content? You can’t cache whole pages then, can you? That’s right, dear Watson. But you can cache the actions. Using action caching means that the request will go trough Action Pack so all the filters are processed before the page gets served. That way you can use authentication and other magic in your pages without having to give up the glory of caching. Here’s an example of controller that uses both page and action caching, stolen straight from the api docs:


  class ListsController < ApplicationController
    before_filter :authenticate, :except => :public
    caches_page   :public
    caches_action :show, :feed
  end

This controller has a public action and two private actions that need authentication — and thus action-level caching.

The most granular way to do caching in Rails is fragment caching. It’s what the two higher-level caching schemes use internally. Using fragment caching is a gem when you have pages that have both highly dynamic and pretty static parts. The downside is that it’s a bit more work and you have to do it in templates. Here’s an example of fragment caching:


  <b>Hello <%= @name %></b>
  <% cache(binding) do %>
    All the topics in the system:
    <%= render_collection_of_partials "topic", Topic.find_all %>
  <% end %>

There. But, wait! What if the content changes in between. Will the users be served old stinkin’ cheese ever after. Glad you asked. It turns out David did notice this possibility. That’s why controllers now have methods like expire_page, expire_action and expire_fragment, for all you busy bees who can’t settle with the content you once created. Here’s an action where the cache for page show is flushed:


  class WeblogController < ActionController::Base
    def update
      List.update(@params["list"]["id"], @params["list"])
      expire_page :action => "show", :id => @params["list"]["id"]
      redirect_to :action => "show", :id => @params["list"]["id"]
    end
  end

OK, enough rambling. Now, go create some apps swift as an arrow.

Oh, one more thing. Rails can use a bunch of different methods to store the cache. But that’s another story.