It appears that Rails controller will no longer be limited to file-based page and fragment caching. There is a lot of work being done in the 2-1-caching branch of Rails that will let you specify your preferred caching engine in the config file. To date there are the following options:
1 2 3 4 |
ActionController::Base.cache_store = :memory_store ActionController::Base.cache_store = :file_store, "/path/to/cache/directory" ActionController::Base.cache_store = :drb_store, "druby://localhost:9192" ActionController::Base.cache_store = :mem_cache_store, "localhost" |
If none is specified, then ActiveSupport::Cache::MemoryStore will be used.
Write Your Own Controller Cache
Interested in writing your own controller caching mechanism? Here are some basic steps:
1. Implement the Cache Class
The easiest way to write your own cache class is to subclass ActiveSupport::Cache::Store and implement the read, write, delete and delete_matched methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
module ActiveSupport module Cache # Pluck and store stuff in the ether. # ('Ether' is fictitious - ignore its implementation) class EtherStore < Store def initialize(location='//myloc') @ether = Ether.new(location) end def read(name, options = nil) super @ether.get(name) end def write(name, value, options = nil) super @ether.store(name, value) end def delete(name, options = nil) super @ether.remove(name) end def delete_matched(matcher, options = nil) super @ether.remove_by_pattern(matcher) end end end end |
- Invoking
superfor each method call ensures that the proper messages get logged for each action - If the underlying cache mechanism doesn’t support a specific operation (such as
delete_matched), have your implementation just raise an exception:raise "delete_matched not supported by Mechanism" - The
optionsargument passed to each method is taken directly from the various top-level cache methods which now accept an options hash (you now have a method to pass in options applicable to your caching mechanism). I.e.in your view when fragment caching:
1 2 3 |
<% cache('name', :expires_in => 60) do %> <%= render :partial => "menu" %> <% end %> |
2. Plug-in Cache
Once you have your implementation (and it’s tested, of course), plug it into your app with a simple one-liner in environment.rb:
1 2 |
# Or EtherStore.new('//etherloc') ActionController::Base.cache_store = :ether_store, '//etherloc' |
There you go, that’s all there is to it.
I’m not sure what the intent is for this functionality, but as of now it only exists in the 2-1-caching branch of rails, I will update this post when it makes it to edge.
tags: ruby, rubyonrails

I’m pretty sure that this does not increase the number of caching options available. You can write a custom fragment store already, and you can use other than the file based simplistic route. I’m right now using a memcache for storage and the setup is as simple like:
<table class="CodeRay"><tr> <td title="click to toggle" class="line_numbers" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"></td> <td class="code"></td> </tr></table>Note how all the magic is really in the last line, the other is just memcache config.
The 2-1-caching branch seems more about refactoring than a features, perhaps the gzip compression could be called a feature but even there i feel it is more about elegance.
Hit by the Mephisto code in comment bug ;-)
And you can use plugins like memcache_fragments (http://agilewebdevelopment.com/plugins/memcache_fragments_with_time_expiry) to get Rails to play nicely with memcache-client, making it easy to do supa-fast action caching with memcache without having to worry about expiring stale caches:
http://www.bencurtis.com/archives/2007/12/painless-rails-action-caching-with-memcached/#more-111
Thanks for the nice read, keep up the interesting posts.