2013-10-20 09:00:00 UTC

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 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 articlesweeper.rb and call the `expirepage` 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