What exactly is caching and how do rails try to achieve it. Well basically rails provide us with an automatic caching feature which help us in increasing the speed of our site by reducing the amount of time consumed by making frequent call to either database or controllers for the same piece of data.
On a high level rails provide us with 3 types of caching :
1) Page caching
2) Action caching
3) Fragment caching
To make use of rails caching feature it need to be enabled in respective files like development.rb,staging.rb etc. By default caching is turned off for development environment. To enable caching just make the following change in respective file :
config.action_controller.perform_caching = true
Page Caching
It is a mechanism where rails store cached controller action in a file format. By default all the cached pages are stored in public folder. In order to achieve page caching we have to follow the following approach :
class BlogsController < ApplicationController
caches_page :index
def index
@blogs = Blog.all
end
end
In this caches_page :index is the keyword used for caching the page which will be cached as blog.html in public folder. We seldom need to update cache when we either update or delete a record to achieve this we need to add the following code :
class BlogsController < ApplicationController
caches_page :index
def index
@blogs = Blog.all
end
def create
expire_page :action => :index
@blog = Blog.new(params[:blog])
@blog.save
end
def update
expire_page :action => :index
@blog = Blog.find(params[:id])
@blog.update_attributes(params[:blog])
end
end
Place where rails cached pages are stored can be changed using the following configuration option
config.action_controller.page_cache_directory =
Action Caching
Action caching similar to page caching except that it is based on filters i.e certain conditions that need to be satisfied in order to access that page
The syntax for doing action cache is :
class BlogsController < ApplicationController
before_filter :authenticate
caches_action :index
def index
@blogs = Blog.all
end
end
Only difference being caches_action :index in place of caches_page :index
For making caching based on certain conditions for action cache we need to add the following conditions:
class BlogsController > ApplicationController
caches_action :index, :if => Proc.new{|c|!c.request.format.json?}
def index
@blogs = Blog.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @blogs }
format.csv
end
end
end
Fragment Caching
Page caching and Action caching both cache entire web page for the user , what if there are small fragments that need to be cached separately for a particular page. To achieve this fragment caching came into existence which does not cache the entire page but try to cache page in small sections.
Below is the example which shows fragment caching taking example of comments for a user :
<div>
<%= @blog.title %><%= @blog.desc %>
</div>
<%cache("blog_comments_#{@blog.id}") do%>
<h3>Comments</h3>
<% @blog.comments.each_with_index do|c, i|%>
<div><%= c.value%><span><%= c.created_at.strftime('%B %d %Y')%></span></div>
<%end%>
<%end%>
<%= link_to 'Add New comment', new_blog_comment_path(@blog)%>
here comments are cached based on their id like "blog_comments_#{@blog.id}" i.e blog_comments_1 etc. If a user delete or update the comment we can update the cache using the following approach :
class BlogsController < ApplicationController
def create
@blog = Blog.find params[:blog_id]
expire_fragment("blog_comments_#{@blog.id}")
@comment = @blog.comments.new(params[:comment])
end
end
Although we have been using code in controller to expire cache but rails provide us with a better way of doing it based on the models which take care of when a record has been added or deleted to achieve this we make use of Sweepers.
Sweepers are responsible expiring caches . They observe models and execute callbacks as defined in the sweeper.
class BlogSweeper < ActionController::Caching::Sweeper
observe Blog
def after_update(blog)
expire_action(:controller => :blogs, :action => :index)
end
def after_create(blog)
expire_action(:controller => :blogs, :action => :index)
end
end
All you need to do is call this sweeper in your controller as :
class BlogController < ApplicationController
cache_sweeper :blog_sweeper, :only => [:index]
end
0 Comment(s)