Tag: caching


Page Caching by Subdomain in Rails and Nginx

Posted By Ryan Stout on July 30, 2010

I'm internationalizing an app, and am splitting the locales by subdomain (es.bustaname.com, fr.bustaname.com, etc...) While other people have solved the page_caching issue with subdomains before, I couldn't find a clear explanation. All of the examples were missing one piece of information.

Controller

Add the following into your controller.

class ApplicationController < ActionController::Base
  # Cache pages with the subdomain
  def cache_page(content = nil, options = nil)
    path = "/#{request.host}/"
    path << case options
    when Hash
      url_for(options.merge(:only_path => true, :skip_relative_url_root => true, :format => params[:format]))
    when String
      options
    else
      if request.path.empty? || request.path == '/'
        '/index'
      else
        request.path
      end
    end
    super(content, path)
  end
end

This will cache each subdomain in its own directory.

To keep things clean I also move my cache directory into public/cache Just add the following to your environment.rb inside of the run block.

Rails::Initializer.run do |config|
	config.action_controller.page_cache_directory = RAILS_ROOT + '/public/cache/'
end

Then the part everyone else seemed to miss is that this will make something like caches_page :index (note the pluralization) work, even though we defined a cache_page method. ActionController::Base has both a class and an instance version of cache_page and a class method called cache_pages. You want to use the class method cache_pages.

Nginx

Next place the following in your nginx.conf file:

# If the file exists in the public folder, send it
if (-f $request_filename) {
  break;
}

# Check / files with index.html
if (-f $document_root/cache/$host/$uri/index.html) {
  rewrite (.*) /cache/$host/$1/index.html break;
}

# Check the path + .html
if (-f $document_root/cache/$host/$uri.html) {
  rewrite (.*) /cache/$host/$1.html break;
}

# Check directly
if (-f $document_root/cache/$host/$uri) {
  rewrite (.*) /cache/$host/$1 break;
}

This will look up cached files in /cache/$host/ and should send the files correctly. Be sure to add the nginx config before you send it to mongrel/thin/etc..


Tags: rails, caching, subdomain, cache_page, nginx