rails Page caching with Rails 4

20 Oct 2013
The built-in page caching has been extracted to a separate gem in Rails 4 and here is a guide how to use it. First we need to add the gem to our Gemfile:
gem 'actionpack-page_caching'
Than in the application controller we need to specify the folder to store our cache files:
class ApplicationController < ActionController::Base
  include ActionController::Caching::Pages
  self.page_cache_directory = "#{Rails.root.to_s}/public/page_cache"
end
Let's say we have an article controller and we want to cache the index and the show action:
class ArticleController < ApplicationController
  caches_page :index, :show
  # Rest of the file omitted.
end
Now if we have the `config.action_controller.perform_caching` set to `true` Rails will generated the HTML output of the pages in the cache folder. One more thing we need to do is to tell the webserver to use the cached version if there is one so the request won't even hit our app. With nginx we can achieve this with a configuration like this:
upstream puma_server_domain_tld {
  server unix:/path/to/the/puma/socket;
}
server {
  listen 80;
  server_name domain.tld;
  root /path/to/the/app;
  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    # try the $uri, than the uri inside the cache folder, than the puma socket
    try_files $uri /page_cache/$uri /page_cache/$uri.html @puma;
  }
  location @puma{
    proxy_pass http://puma_server_domain_tld;
    break;
  }
  # set the expire date to max for assets
  location ~ "^/assets/(.*/)*.*-[0-9a-f]{32}.*" {
    gzip_static on;
    expires     max;
    add_header  Cache-Control public;
  }
}
Now we managed to serve the cached version of our pages but we need a way to flush the cache when it needs. To achieve this we will user a Sweeper. In Rails 4 the cache sweepers are also moved to a separate gem with the observers so we need to add the it to the Gemfile:
gem 'rails-observers'
Than we need to create a file in the app/sweepers folder called article_sweeper.rb and call the `expire_page` method with a reference to the page we want to flush the cache for. Let's say we use a user friendly url field for the articles and the cache files will be named after that field. In this case to expire those we will need to pass the raw url string to the method:
class ArticleSweeper < ActionController::Caching::Sweeper
  observe Article

  def after_save(record)
    expire_page(articles_path)
    expire_page("/#{record.url}")
  end
end
That's all, we achieved to setup the page caching for our Rails 4 app. ## Resources actionpack-page_caching rails-observers

I run an indie startup providing vulnerability scanning for your Ruby on Rails app. It is free to use at the moment, and I am grateful for any feedback about it.
If you would like to give it a spin, you can do it here: Vulnerability Scanning for your Ruby on Rails app!

Did you enjoy reading this? Follow me on Twitter or sign up to my newsletter for more content like this!

Related posts