Rails Page Caching and Internationalization
How to hack your Rails application to configure how page caches are stored
Rails offers an effective caching solution for caching pages using page_caching. This stores the entire output of a request into a publicly accessible file which is then picked up by the web server first before the request is made to Rails. The Rails default method to set the path of the is something that doesn’t take the locale nor the subdomain into consideration. So if you have a subdomain that is bound to the same Rails server, then the page caching will not append any of that to the name of the cached page file. This blog article will explain how to change this behaviour.
Last Updated
This page was last updated on December 29th 2011 and was first published on May 9th 2012
How (where) Rails stores its page cached files
The page that Rails (up to and including its latest version Rails 3.1) stores its page caches are in /public folder of the project root. This configuration can be configured within the application.rb file by setting the following configuration:
config.action_controller.page_cache_directory = Rails.root.to_s + "/public"
When a caches_page directive is set within a controller for a particular action then the page caching sets up the path of the URL to be the path of the cache file. This can be changed within some function overriding.
How to override it
In your app/controllers/application_controller.rb set the following code to change the way that the file is written. Here is the default:
def self.page_cache_path(path,extension) # Default MyApp::Application.config.action_controller.page_cache_directory + path + extension end
Now lets imagine if you were to include the locale into the mix:
def self.page_cache_path(path,extension) # Appending the locale path += '-' + I18n.locale.to_s # /users/1/search will be stored as public/users/1/search-en.html (or without the .html) MyApp::Application.config.action_controller.page_cache_directory + path + extension end
And we can also include the subdomain. Lets imagine that www is the default locale … English (en) and anything else is non-www. The only issue is that the page_cache_path method is a class-level method (static) so the request object won’t be recognized by the class method. We’ll need to add a class variable as a before filter:
before_filter :prepare_subdomain def prepare_subdomain @@subdomain = request.subdomains.first.to_s end def self.page_cache_path(path,extension) path += '-' + @@subdomain MyApp::Application.config.action_controller.page_cache_directory + path + extension end
Configuring your HTTP Server
So far I’ve only done this with NGINX. What needs to be done is to configure your NGINX server to recognize that the page cached file is there before it fires up the Rails request. Here is my configuration file:
server { listen 80; server_name ~^(\w+).mydomain.com$; set $subdomain $1; if (-f $document_root/$uri-$subdomain.html) { rewrite (.*) /$1-$subdomain.html break; } }
It will take alot of trial and error with getting NGINX to fully recognize your page cached files. Therefore, its better to install NGINX locally and change the HOSTS configuration a proper domain to point on your computer and perfect it that way. Keep in mind that NGINX does not allow AND and OR pre-conditions or nested if statements so you’ll need to use concatenation and variable checking to get something complex to work.
[...] http://yearofmoo.com/2011/12/rails-page-caching-and-internationalization/ [...]