In Rails we have two different ways of Caching
- Page Caching: which is always stored on Disk
- Action & Fragment Caching: which uses the configure cache configured in our Rails instance.
By default Rails provides three techniques:
1) Page Caching
Allows the request for a generated page to be fulfilled by the webserver, without ever having to go to your RoR application.
In other words if you have page caching turned on, the request will come in, go to Mongrel, the page will then be generated, and then sends it back to apache. Additionally, it will be stored in a local file system. Next time we request the same page, apache will load the page from the filesystem and send it back to the client, without your Rails application being called at all.
To turn on page caching you need to make sure “perform_caching” is set to true for your environment. This flag is normally set in the corresponding config/environments/*.rb
By default, caching is disabled for development and test, and enabled for production.
config.action_controller.perform_caching = true
The next step is to cache the action(s) in the controller by using the page-caching approach that will store the cache in a path.
caches_page :index, :show
Page Cache options
We can cache any filesystem format (json, xml, iphone) by using the Rails response format.
The page caching mechanism will automatically add the appropriate corresponding extensions: /public/users.html; public/users.xml; public/users.json; public/users.iphone.
By default it gets cached under public/<name>.html. Changing the default helps avoid naming conflicts, since we put static html in public/. To do this, it will require web server reconfiguration to let the web server know from where to serve the cached files .
Rails::Initializer.run do |config| config.action_controller.page_cache_directory = "#{RAILS_ROOT}/public/cache" ... end
Quick Tips
Page caching ignores all parameters, so if your request is http://mysite.com/users?page=1, it will be written out as public/users.html. A request like http://mysite.com/users?page=3, will be served as users.html. To avoid this you might consider changing your routes.rb
2) Action Caching
Action caching works like page caching except that the incoming web request goes from the web server to the Rails apps. It does this so that before_filters can be run before the cache file is served. This allows you to use authentication and other restrictions while still serving the results of the request from a cached copy.
We want to use action caching while running “filters” or executing code in the views, but remember the content is always the same. So in your controller you will call :
caches_action :show
before_filter :autenticate, :only => [:show]
Action Caching Options
You can set different ways of cachings in /config/environments/development.rb
- as a temp file (ActiveSupport::Cache::FileStore)
- as a memory store (ActiveSupport::Cache::MemoryStore)
- as mem_cache (ActiveSupport::Cache::MemCacheStore)
Including different options such as:config.cache_store = :mem_cache_store
- as drb_store (ActiveSupport::Cache::DRbStore)
- as custom_store
config.cache_store = :drb_store
To use action caching, add the method caches_action: <action> to your Controller
Features
1. Cache the action without the layout.
class PostsController < ApplicationController caches_action :index, :show before_filter :autenticate, :only => [:show], :layout => false ....... end
It will only cache your action content. Note: If you need some sort of data you might want to use before_filter and set you instance variables.
2. Conditional Action action using :if (or :unless) => Proc.new{….} to specify when the action should be cached.
3. Specific path using :cache_path => Proc.new { |controller| ….} or
:cache_path => {:expires_in =>1.hour }, to specify when the action should be cached. (only with memcached & rails > 2.1)
3) Fragment Caching
Fragment caching allows you to fragment many pieces of the view. The pieces will be wrapped in a cache block and served out of the cache store when the next request comes in. Fragment caching is useful for dynamic web applications.
When the same request comes in again, we pull the different pieces out of the cache, combine them into a single page, and send it back to the client.
To implement fragment caching, cache your method in the view:
<% cache (:recent_joined) do %> <% @recent_joined.each do |user| %> ......... <% end %> <%end>
And you will see the fragment key in the log, which are prefixed with “views/”