Agile Web Development

Build it. Launch it. Love it.

johnny_cache

Problem: You’re enjoying the performance benefits of fragment caching, but managing the cache using sweepers is not really appropriate for some fragments. Instead, you’d rather have a “time to live” option for a cached fragment, so that the cache would be expired and the fragment regenerated only if it has passed a certain age.
Solution: Of course, there are many ways to skin this cat. In the end, I settled on somewhat of a hack. However, this solution will work no matter what storage option you are using for caching.
Basically, the plugin overrides cache and cache_erb_fragment, inserting an HTML comment into the beginning of the block of HTML being cached. This HTML comment contains a timestamp (using the to_i method on a Ruby Time object) which marks the time (in UTC) at which the fragment expires. The next time cache is called, the fragment gets read, the timestamp can be checked, and the fragment can be expired or preserved depending on the current time.
Examples
In a view:
  <% cache("some_fragment", :time_to_live => 5.minutes) do -%>
    This fragment was cached at 
      <%= Time.now.utc.strftime "%H:%M:%S on %m/%d/%Y" %> 
    and will expire at: 
      <%= 5.minutes.from_now.utc.strftime "%H:%M:%S on %m/%d/%Y" %> (UTC)
  <% end %>

In a controller:
  # instead of: read_fragment("some_fragment"), try:
  unless get_johnny_cache("some_fragment")
    # make some expensive DB queries
  end

h3. Installation
script/plugin install http://svn.offtheline.net/plugins/johnny_cache/

(or use piston or whatever you prefer)
Notes
* Remember: If you want to play with caching and you’re working in the development environment, you need to enable caching. Find the perform_caching line in environments/development.rb and change it to true, and restart your server. If you don’t make this change, you’re never caching any fragments, and therefore, this plugin won’t do anything for you (in development; caching is turned on by default for the production environment). * Works in Rails 2.0.2 and the example also works in Rails 2.1.0; however, the tests I wrote for the plugin only work in Rails 2.0.2. Apparently they changed something about the way you test ERB in 2.1.0 and I haven’t had a chance to figure out what’s wrong. * I assume this only works for ERB fragment caching and not Haml (or any other HTML generator). However, the code for the plugin is pretty simple and it should be easy to adapt it to Haml if you desire.

Vitals

Home http://offtheline.net/2008/7/10/timestamping-fragment-caches
Repository http://svn.offtheline.net/plugins/johnny_cache/
License Rails' (MIT)
Tags Tag_red caching fragment timestamp
Rating (1 vote)
Owner Jason LaPier
Created 28 September 2008

Comments

  • Avatar
    18 November 2008

    Due to changes in rendering fragments, this no longer works in Rails 2.2. However, it is an easy fix.

    Change like 4 to: @controller.cache_erb_fragment(output_buffer, block, name, options)

    Line 10 to: def cache_erb_fragment(buffer, block, name = {}, options = {})

    And comment out line 14:

    buffer = eval(ActionView::Base.erb_variable, block.binding)

    That does the trick.

Add a comment