How to setup and use Rack::Cache with Rails 2.3
First install rack-cache:
1 sudo gem install rack-cache
Install Rails version 2.3 or greater:
1 sudo gem install rails
Or, freeze your project to Rails edge:
1 cd project 2 rake rails:freeze:edge
Add this to config/environment.rb:
1 config.middleware.use Rack::Cache, 2 :verbose => true, 3 :metastore => 'file:/var/cache/rack/meta', 4 :entitystore => 'file:/var/cache/rack/body'
Note the name is middleware, not middlewares which is used in all examples I found online, even the Rails blog.
Check the Rack configuration:
1 rake middleware
You should see something like this:
1 use Rack::Lock 2 use ActionController::Failsafe 3 use ActionController::Reloader 4 use ActionController::Session::CookieStore, #<Proc:0x00002b45ab39e3a8@(eval):8> 5 use ActionController::RewindableInput 6 use ActionController::ParamsParser 7 use Rack::MethodOverride 8 use Rack::Head 9 use Rack::Cache, {:metastore=>"file:/var/cache/rack/meta", :entitystore=>"file:/var/cache/rack/body", :verbose=>true} 10 use ActiveRecord::QueryCache 11 run ActionController::Dispatcher.new
Tell Rack to cache data by putting this in your controller:
1 expires_in 5.minutes, :public => true
Note that you should avoid caching private data when the user is signed in. In this case you should set the Cache-Control header to private or completely avoid using expires_in:
1 expires_in 5.minutes, :public => true if !signed_in?
Rails sets cache-control to private by default, Rack needs public content.
With verbose set to true, you’ll see this in the thin logs:
1 [cache] trace: cache miss 2 [cache] trace: fetching response from backend 3 [cache] trace: store backend response in cache (ttl: 300s) 4 [cache] trace: storing response in cache 5 [cache] trace: delivering response ... 6 [cache] trace: cache hit (ttl: 276s) 7 [cache] trace: delivering response ...
Note that ActionController::AbstractRequest has been renamed to ActionController::Request in Rails 2.3.0, so some plugins might throw this error in your face:
1 load_missing_constant': uninitialized constant ActionController::AbstractRequest
Problems
If you get one of these errors you need to change the way you require the rack-cache gem:
1 uninitialized constant Rack::Cache 2 3 uninitialized constant Rails::Rack::CacheI’ve found that this doesn’t work:
1 config.gem "rack/cache", :lib => 'rack/cache'
Instead, I’m requiring rack-cache by adding this to environment.rb:
1 require 'rack-cache' 2 3 4 Rails::Initializer.run do |config|
References
HTTP RFC – Cache-Control
Rack::Cache options documentation
Rails expires_in documentation
How to cache PHP objects to disk with CakePHP
CakePHP has a view cache (similar to Rails) that can be used to cache objects. The following snippet shows a CakePHP action that uses the serialize and unserialize functions to cache a tag cloud—an array containing tags in this case—to disk, and then read it back.
Note that we assign a TTL of 1 hours to the tag cloud, so if it’s more than one hour old it will be refreshed from the database.
1 function index() 2 { 3 $maximum = 100; 4 $cache_key = "tag_cloud_$maximum"; 5 $tag_cloud = cache($cache_key, null, '+1 hours'); 6 7 if(empty($tag_cloud)) 8 { 9 $tag_cloud = Tag::generate_cloud($maximum); 10 cache($cache_key, serialize($tag_cloud)); 11 } 12 else 13 { 14 $tag_cloud = unserialize($tag_cloud); 15 } 16 17 return $tag_cloud; 18 }
The cache function is defined in $APP_ROOT/cake/basics.php, which is where you should look if you want to know more about how the caching works…