SlideShare a Scribd company logo
Caching, in the web application world, is the art of
taking a processed web page (or part of a webpage), and
storing it in a temporary location. If another user
requests this same webpage, then we can serve up the
cached version.
Loading up a cached webpage can not only save us from
having to do ANY database queries (i.e. no more rountd
trips to server), it can even allow us to serve up
websites without touching our Ruby on Rails Server.
nd all this with lightning speed…
 There's only one thing you'll need to do to start playing

with caching.
 Look for the following line and change it to true in your
/config/environments/development.rb:
config.action_controller.perform_caching = true
NOTE: By default, caching is disabled for development and test, and enabled for production.
 There are three types of caching techniques that Rails

provides by default without the use of any third party
plugins.
Page Caching
2) Action Caching
3) Fragment Caching
1)
 Page caching is the FASTEST Rails caching

mechanism, so you should do it if at all possible.
 Where should you use page caching?
 If your page is the same for all users.

 If your page is available to the public, with no

authentication needed.
 It can’t be applied to every situation (such as pages that

need authentication)
 Since the webserver is literally just serving a file from
the filesystem, cache expiration is an issue that needs
to be dealt with.
 Say we have a blog page (Imagine that!) that doesn't

change very often. The controller code for our front
page might look like this:
 As you can see, our List action queries the latest 10

blog posts, which we can then display on our webpage.
If we wanted to use page caching to speed things up,
we could go into our blog controller and do:
 The "caches_page" directive tells our application that

next time the "list" action is requested, take the
resulting html, and store it in a cached file.
 Subsequent requests to the same url will now hit this
html file rather then reloading the page. As you can
imagine, loading a static html page is much faster than
loading and processing a interpreted programming
language.
 Like 100 times faster!
 However, it is very important to note that Loading

Page Cached .html files does not invoke Rails at
all! What this means is that if there is any content that
is dynamic from user to user on the page, or the page is
secure in some fashion, then you can't use page
caching. Rather you'd probably want to use action or
fragment caching,
 So, how do you enable this super-fast cache behavior?

Suppose you have a controller called
ProductsController and an index action that lists all
the products. You could enable caching for this action
like this:
class ProductsController <
ActionController caches_page :index def index; end end
 The first time anyone requests products/index, Rails

will generate a file called index.html. If a web server
see this file, it will be served in response to the next
request for products/index, without your Rails
application being called.
 By the way …
 Where all these cached pages get stored ???
 By default, the page cache directory is set to

Rails.public_path (which is usually set to
File.join(self.root, "public") – that is, the public
directory under your Rails application’s root).
 The page caching mechanism will automatically add a

.html extension to requests for pages that do not have
an extension to make it easy for the webserver to find
those pages.
 What if we then say in our model:
 caches_page :show Where do you think the cached

page would get stored when we visited "/blog/show/5"
to show a specific blog post?
 The answer is /public/blog/show/5.html
 Here are a few more examples of where page caches are
stored.:
 Hey, wait a minute, notice how above the first item is

the same as the last item. Yup, page caching is going to
ignore all additional parameters on your url.
 Very interesting question, and a more interesting

answer. In order to cache your different pages, you just
have to create a differently formed url. So instead of
linking "/blog/list?page=2", which wouldn't work
because caching ignores additional parameters, we
would want to link using "/blog/list/2", but instead of
2 being stored in params[:id], we want that 2 on the
end to be params[:page].
 We can make this configuration change in our
/config/routes.rb
 the resulting url will be "/blog/list/2". When we click

this link two great things will happen:
 Rather than storing the 2 in params[:id], which is the
default, the application will store the 2 as
params[:page],
 The page will be cached as /public/blog/list/2.html
 The moral of the story is; If you're going to use page
caching, make sure all the parameters you require are
part of the URL, not after the question mark!
 In order to expire this page when a new product is

added you could extend the products controller like
this:
class ProductsController <
ActionController caches_page :index def index; end def
create expire_page :action => :index end end
 action caching works like page caching except for the

fact that the incoming web request does go from the
web server to the Rails stack and Action Pack so that
before filters can be run on it before the cache is
served. This allows you to use authentication and other
restrictions while still serving the result of the output
from a cached copy.
 Clearing the cache works in the exact same way as with

page caching.
 Let’s say you only wanted authenticated users to edit or

create a Product object, but still cache those pages:
 You can also use :if to pass a Proc that specifies when

the action should be cached.
 Also, you can use :layout => false to cache without
layout so that dynamic information in the layout such
as the name of the logged-in user or the number of
items in the cart can be left uncached.
 This feature is available as of Rails 2.2.
 Unfortunately, dynamic web applications usually build

pages with a variety of components not all of which
have the same caching characteristics.
 In order to address such a dynamically created page

where different parts of the page need to be cached
and expired differently Rails provides a mechanism
called Fragment Caching.
 Fragment Caching allows a fragment of view logic to

be wrapped in a cache block and served out of the
cache store when the next request comes in.
 As an example, if you wanted to show all the orders placed

on your website in real time and didn’t want to cache that
part of the page, but did want to cache the part of the page
which lists all products available, you could use this piece
of code:
Ror caching
 Cache sweeping is a mechanism which allows you to get

around having a ton of expire_{page,action,fragment} calls
in your code.
 It does this by moving all the work required to expire

cached content into ActionController::Caching::Sweeper
class.
 This class is an Observer that looks for changes to an object

via callbacks, and when a change occurs it expires the
caches associated with that object in an around or after
filter.
Ror caching
 Query caching is a Rails feature that caches the result set

returned by each query. If Rails encounters the same query
again during the current request, it will used the cached
result set as opposed to running the query against the
database.



Query caches are created at the start of an action and destroyed at the end of that action
and thus persist only for the duration of the action.
 Rails (as of 2.1) provides different stores for the cached

data created by action and fragment caches. Page
caches are always stored on disk.
 1) ActiveSupport::Cache::MemoryStore: A cache

store implementation which stores everything into
memory in the same process.
 MemoryStoreis not only able to store strings, but also
arbitrary Ruby objects. MemoryStoreis not threadsafe. Use SynchronizedMemoryStore instead if you
need thread-safety.
 2) ActiveSupport::Cache::FileStore: Cached data is

stored on the disk. This is the default store and the
default path for this store is: /tmp/cache.
 Works well for all types of environments and allows all
processes running from the same application directory
to access the cached content. If /tmp/cache does not
exist, the default store becomes MemoryStore.
 3) ActiveSupport::Cache::DRbStore: Cached data is

stored in a separate shared DRb process that all servers
communicate with.
 This works for all environments and only keeps one
cache around for all processes, but requires that you
run and manage a separate DRb process.
 4) MemCached store: Works like DRbStore, but uses

Danga’s MemCache instead. Rails uses the bundled
memcached-client gem by default. This is currently the
most popular cache store for production websites.
Special features:
 Clustering and load balancing. One can specify multiple
memcached servers, and MemCacheStore will load balance
between all available servers. If a server goes down, then
MemCacheStore will ignore it until it goes back online.
 Time-based expiry support. See write and the :expires_in
option.
 Per-request in memory cache for all communication with
the MemCache server(s).
Ror caching
 Conditional GETs are a feature of the HTTP specification

that provide a way for web servers to tell browsers that the
response to a GET request hasn’t changed since the last
request and can be safely pulled from the browser cache.
 They work by using the HTTP_IF_NONE_MATCH and

HTTP_IF_MODIFIED_SINCE headers to pass back and
forth both a unique content identifier and the timestamp
of when the content was last changed. If the browser makes
a request where the content identifier (etag) or last
modified since timestamp matches the server’s version
then the server only needs to send back an empty response
with a not modified status.
 Along with the built-in mechanisms outlined above, a

number of excellent plugins exist to help with finer
grained control over caching.
 These includes

1)

Chris Wanstrath’s excellent cache_fu plugin
http://errtheblog.com/posts/57-kickin-ass-w-cachefu

2) Evan Weaver’s interlock plugin
http://blog.evanweaver.com/articles/2007/12/13/better-railscaching/
 http://guides.rubyonrails.org/caching_with_rails.html
 http://www.railsenvy.com/2007/2/28/rails-caching-

tutorial
 http://www.railsenvy.com/2007/3/20/ruby-on-railscaching-tutorial-part-2
 http://www.ibm.com/developerworks/web/library/wa
-rails1/
Ror caching

More Related Content

Ror caching

  • 1. Caching, in the web application world, is the art of taking a processed web page (or part of a webpage), and storing it in a temporary location. If another user requests this same webpage, then we can serve up the cached version. Loading up a cached webpage can not only save us from having to do ANY database queries (i.e. no more rountd trips to server), it can even allow us to serve up websites without touching our Ruby on Rails Server. nd all this with lightning speed…
  • 2.  There's only one thing you'll need to do to start playing with caching.  Look for the following line and change it to true in your /config/environments/development.rb: config.action_controller.perform_caching = true NOTE: By default, caching is disabled for development and test, and enabled for production.
  • 3.  There are three types of caching techniques that Rails provides by default without the use of any third party plugins. Page Caching 2) Action Caching 3) Fragment Caching 1)
  • 4.  Page caching is the FASTEST Rails caching mechanism, so you should do it if at all possible.  Where should you use page caching?  If your page is the same for all users.  If your page is available to the public, with no authentication needed.
  • 5.  It can’t be applied to every situation (such as pages that need authentication)  Since the webserver is literally just serving a file from the filesystem, cache expiration is an issue that needs to be dealt with.
  • 6.  Say we have a blog page (Imagine that!) that doesn't change very often. The controller code for our front page might look like this:
  • 7.  As you can see, our List action queries the latest 10 blog posts, which we can then display on our webpage. If we wanted to use page caching to speed things up, we could go into our blog controller and do:
  • 8.  The "caches_page" directive tells our application that next time the "list" action is requested, take the resulting html, and store it in a cached file.  Subsequent requests to the same url will now hit this html file rather then reloading the page. As you can imagine, loading a static html page is much faster than loading and processing a interpreted programming language.  Like 100 times faster!
  • 9.  However, it is very important to note that Loading Page Cached .html files does not invoke Rails at all! What this means is that if there is any content that is dynamic from user to user on the page, or the page is secure in some fashion, then you can't use page caching. Rather you'd probably want to use action or fragment caching,
  • 10.  So, how do you enable this super-fast cache behavior? Suppose you have a controller called ProductsController and an index action that lists all the products. You could enable caching for this action like this: class ProductsController < ActionController caches_page :index def index; end end
  • 11.  The first time anyone requests products/index, Rails will generate a file called index.html. If a web server see this file, it will be served in response to the next request for products/index, without your Rails application being called.
  • 12.  By the way …  Where all these cached pages get stored ???
  • 13.  By default, the page cache directory is set to Rails.public_path (which is usually set to File.join(self.root, "public") – that is, the public directory under your Rails application’s root).  The page caching mechanism will automatically add a .html extension to requests for pages that do not have an extension to make it easy for the webserver to find those pages.
  • 14.  What if we then say in our model:  caches_page :show Where do you think the cached page would get stored when we visited "/blog/show/5" to show a specific blog post?  The answer is /public/blog/show/5.html  Here are a few more examples of where page caches are stored.:
  • 15.  Hey, wait a minute, notice how above the first item is the same as the last item. Yup, page caching is going to ignore all additional parameters on your url.
  • 16.  Very interesting question, and a more interesting answer. In order to cache your different pages, you just have to create a differently formed url. So instead of linking "/blog/list?page=2", which wouldn't work because caching ignores additional parameters, we would want to link using "/blog/list/2", but instead of 2 being stored in params[:id], we want that 2 on the end to be params[:page].  We can make this configuration change in our /config/routes.rb
  • 17.  the resulting url will be "/blog/list/2". When we click this link two great things will happen:  Rather than storing the 2 in params[:id], which is the default, the application will store the 2 as params[:page],  The page will be cached as /public/blog/list/2.html  The moral of the story is; If you're going to use page caching, make sure all the parameters you require are part of the URL, not after the question mark!
  • 18.  In order to expire this page when a new product is added you could extend the products controller like this: class ProductsController < ActionController caches_page :index def index; end def create expire_page :action => :index end end
  • 19.  action caching works like page caching except for the fact that the incoming web request does go from the web server to the Rails stack and Action Pack so that before filters can be run on it before the cache is served. This allows you to use authentication and other restrictions while still serving the result of the output from a cached copy.  Clearing the cache works in the exact same way as with page caching.
  • 20.  Let’s say you only wanted authenticated users to edit or create a Product object, but still cache those pages:
  • 21.  You can also use :if to pass a Proc that specifies when the action should be cached.  Also, you can use :layout => false to cache without layout so that dynamic information in the layout such as the name of the logged-in user or the number of items in the cart can be left uncached.  This feature is available as of Rails 2.2.
  • 22.  Unfortunately, dynamic web applications usually build pages with a variety of components not all of which have the same caching characteristics.  In order to address such a dynamically created page where different parts of the page need to be cached and expired differently Rails provides a mechanism called Fragment Caching.
  • 23.  Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in.
  • 24.  As an example, if you wanted to show all the orders placed on your website in real time and didn’t want to cache that part of the page, but did want to cache the part of the page which lists all products available, you could use this piece of code:
  • 26.  Cache sweeping is a mechanism which allows you to get around having a ton of expire_{page,action,fragment} calls in your code.  It does this by moving all the work required to expire cached content into ActionController::Caching::Sweeper class.  This class is an Observer that looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.
  • 28.  Query caching is a Rails feature that caches the result set returned by each query. If Rails encounters the same query again during the current request, it will used the cached result set as opposed to running the query against the database.  Query caches are created at the start of an action and destroyed at the end of that action and thus persist only for the duration of the action.
  • 29.  Rails (as of 2.1) provides different stores for the cached data created by action and fragment caches. Page caches are always stored on disk.
  • 30.  1) ActiveSupport::Cache::MemoryStore: A cache store implementation which stores everything into memory in the same process.  MemoryStoreis not only able to store strings, but also arbitrary Ruby objects. MemoryStoreis not threadsafe. Use SynchronizedMemoryStore instead if you need thread-safety.
  • 31.  2) ActiveSupport::Cache::FileStore: Cached data is stored on the disk. This is the default store and the default path for this store is: /tmp/cache.  Works well for all types of environments and allows all processes running from the same application directory to access the cached content. If /tmp/cache does not exist, the default store becomes MemoryStore.
  • 32.  3) ActiveSupport::Cache::DRbStore: Cached data is stored in a separate shared DRb process that all servers communicate with.  This works for all environments and only keeps one cache around for all processes, but requires that you run and manage a separate DRb process.
  • 33.  4) MemCached store: Works like DRbStore, but uses Danga’s MemCache instead. Rails uses the bundled memcached-client gem by default. This is currently the most popular cache store for production websites. Special features:  Clustering and load balancing. One can specify multiple memcached servers, and MemCacheStore will load balance between all available servers. If a server goes down, then MemCacheStore will ignore it until it goes back online.  Time-based expiry support. See write and the :expires_in option.  Per-request in memory cache for all communication with the MemCache server(s).
  • 35.  Conditional GETs are a feature of the HTTP specification that provide a way for web servers to tell browsers that the response to a GET request hasn’t changed since the last request and can be safely pulled from the browser cache.  They work by using the HTTP_IF_NONE_MATCH and HTTP_IF_MODIFIED_SINCE headers to pass back and forth both a unique content identifier and the timestamp of when the content was last changed. If the browser makes a request where the content identifier (etag) or last modified since timestamp matches the server’s version then the server only needs to send back an empty response with a not modified status.
  • 36.  Along with the built-in mechanisms outlined above, a number of excellent plugins exist to help with finer grained control over caching.  These includes 1) Chris Wanstrath’s excellent cache_fu plugin http://errtheblog.com/posts/57-kickin-ass-w-cachefu 2) Evan Weaver’s interlock plugin http://blog.evanweaver.com/articles/2007/12/13/better-railscaching/
  • 37.  http://guides.rubyonrails.org/caching_with_rails.html  http://www.railsenvy.com/2007/2/28/rails-caching- tutorial  http://www.railsenvy.com/2007/3/20/ruby-on-railscaching-tutorial-part-2  http://www.ibm.com/developerworks/web/library/wa -rails1/