Rails Page Caching Travis Roberts http://travisonrails.com http://twitter.com/travisroberts
Why Cache? Significantly speed up page load. Reduce resource usage on server.
But, How Do We Do It? in config/environments/development.rb in app/controllers/[controller_name].rb in config/environment.rb config.action_controller.perform_caching  =   true caches_page :index, :show, :feed # Move the cached files into their own directory   config.action_controller.page_cache_directory  =  RAILS_ROOT  +   "/public/cache/"
What About New Content? New content won’t show, so we have to expire the cache in config/environment.rb This tells the application to load our “sweepers” dir We put the expire logic in the sweepers config.load_paths  +=   %W(   #{RAILS_ROOT}/app/sweepers )
Quick and Dirty Sweeper class   SiteSweeper   < ActionController::Caching::Sweeper   observe Post, Comment   def   after_save (record)   self.class::sweep   end     def   after_destroy (record)   self.class::sweep   end     def   self.sweep   cache_dir  =   ActionController :: Base .page_cache_directory   unless  cache_dir  ==  RAILS_ROOT + &quot;/public&quot;   FileUtils .rm_r( Dir .glob(cache_dir + &quot;/*&quot; ))  rescue   Errno ::ENOENT   RAILS_DEFAULT_LOGGER .info( &quot;Cache directory fully swept.&quot; )   end   end end
We Can Do Better in app/sweepers/post_sweeper.rb class   PostSweeper   < ActionController::Caching::Sweeper   observe Post   def   after_save (post)   expire_pages(post)   end     def   after_destroy (post)   expire_pages(post)   end     def   expire_pages (post)   expire_page(blog_path(:page =>  nil ))  # expire blog index (/blog/list)   expire_page(blog_path(post))  # expire detail page (/blog/12)   # if we need to remove  an  entire directory in the cache   cache_dir  =   ActionController :: Base .page_cache_directory   FileUtils .rm_r( Dir .glob(cache_dir + &quot;/blog/list/*&quot; ))  rescue   Errno ::ENOENT  # expire list   RAILS_DEFAULT_LOGGER .info( &quot;Cache directory for blog successfully swept.&quot; )   end end
Calling the Sweeper We need to tell our controller when to invoke the sweeper in app/controllers/post_controller.rb class   Manage::PostsController   < ApplicationController   cache_sweeper :post_sweeper, :only => [:create, :update, :destroy]     # other code...   end
Tell the Server to Use Cache Add the following lines to your .conf file # Rewrite index to check for static index RewriteRule ^/$ /cache/index.html [QSA] # Rewrite to check for cached pages  RewriteRule ^([^.]+)$ /cache/$1.html [QSA]
What about pagination? With default pagination, caching won’t work (site.com/blog?page=2) We need to add a route for caching map.blog_list  'blog/list/:page' ,  :controller  =>  'blog' ,  :action  =>  'index' ,   :requirements  => { :page  =>  / \d +/ },  :page  =>  nil # This will add the following routes  # blog_list_path => site.com/blog/list  # blog_list_path(:page => 3) => site.com/blog/list/3
The End! Questions? Comments?

Rails Page Caching

  • 1.
    Rails Page CachingTravis Roberts http://travisonrails.com http://twitter.com/travisroberts
  • 2.
    Why Cache? Significantlyspeed up page load. Reduce resource usage on server.
  • 3.
    But, How DoWe Do It? in config/environments/development.rb in app/controllers/[controller_name].rb in config/environment.rb config.action_controller.perform_caching = true caches_page :index, :show, :feed # Move the cached files into their own directory config.action_controller.page_cache_directory = RAILS_ROOT + &quot;/public/cache/&quot;
  • 4.
    What About NewContent? New content won’t show, so we have to expire the cache in config/environment.rb This tells the application to load our “sweepers” dir We put the expire logic in the sweepers config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
  • 5.
    Quick and DirtySweeper class SiteSweeper < ActionController::Caching::Sweeper observe Post, Comment def after_save (record) self.class::sweep end def after_destroy (record) self.class::sweep end def self.sweep cache_dir = ActionController :: Base .page_cache_directory unless cache_dir == RAILS_ROOT + &quot;/public&quot; FileUtils .rm_r( Dir .glob(cache_dir + &quot;/*&quot; )) rescue Errno ::ENOENT RAILS_DEFAULT_LOGGER .info( &quot;Cache directory fully swept.&quot; ) end end end
  • 6.
    We Can DoBetter in app/sweepers/post_sweeper.rb class PostSweeper < ActionController::Caching::Sweeper observe Post def after_save (post) expire_pages(post) end def after_destroy (post) expire_pages(post) end def expire_pages (post) expire_page(blog_path(:page => nil )) # expire blog index (/blog/list) expire_page(blog_path(post)) # expire detail page (/blog/12) # if we need to remove an entire directory in the cache cache_dir = ActionController :: Base .page_cache_directory FileUtils .rm_r( Dir .glob(cache_dir + &quot;/blog/list/*&quot; )) rescue Errno ::ENOENT # expire list RAILS_DEFAULT_LOGGER .info( &quot;Cache directory for blog successfully swept.&quot; ) end end
  • 7.
    Calling the SweeperWe need to tell our controller when to invoke the sweeper in app/controllers/post_controller.rb class Manage::PostsController < ApplicationController cache_sweeper :post_sweeper, :only => [:create, :update, :destroy] # other code... end
  • 8.
    Tell the Serverto Use Cache Add the following lines to your .conf file # Rewrite index to check for static index RewriteRule ^/$ /cache/index.html [QSA] # Rewrite to check for cached pages RewriteRule ^([^.]+)$ /cache/$1.html [QSA]
  • 9.
    What about pagination?With default pagination, caching won’t work (site.com/blog?page=2) We need to add a route for caching map.blog_list 'blog/list/:page' , :controller => 'blog' , :action => 'index' , :requirements => { :page => / \d +/ }, :page => nil # This will add the following routes # blog_list_path => site.com/blog/list # blog_list_path(:page => 3) => site.com/blog/list/3
  • 10.