Кеширование страниц средствами Ruby on Rails

February 25, 2010, revised March 6, 2011 Apache nginx RentFeed Ruby on Rails кеширование

Я тут занялся оптимизированием RentFeed, где большую часть страниц можно положить в кеш и обновлять несколько раз в день. Самый тупой и быстрый кеш в виде статических файлов, отдаваемых непосредственно апачем.

Более сложный случай кеширования рассматривается в статье Кеширование страниц с динамическими элементами средствами Ruby on Rails.

Рельсы умеют такое делать “из коробки”, практически одной строчкой:

class SomeController < ApplicationController
  caches_page :index

  def index
  end
end

Все! Кеш уже работает. Правда, почему-то рельсы не предусматривают две вещи. Кеш не работает с GET-параметрами - раз. 
Хранится прямо в `public` - два.

## GET-параметры

Тут все просто: хочешь, чтобы для разного набора параметров кешировались разные страницы - помещай параметры в путь. 
Кстати, к таким ссылкам и Google лучше относится.

Для меня это в первую очередь касалось постраничной разбивки. Если ты используешь [will_paginate](https://github.com/mislav/will_paginate), то тебе 
достаточно вынести URL с номером страницы в таблицу роутов:

### Rails 2.3

ruby

config/routes.rb

map.resources :items map.paged_items ‘/items/page/:page’, :controller => ‘items’, :action => ‘index’


### Rails 3

ruby

config/routes.rb

resources :items get ‘/items/page/:page’, :to => ‘items#index’, :as => :paged_items


## Перемещаем кеш в более удобное место (например, в `public/cache`)

Путь к кешу указывается в конфиге:

ruby

config/environments/production.rb

config.action_controller.page_cache_directory = File.join(Rails.root, ‘public’, ‘cache’)


Осталось научить Apache забирать кеш из нужного каталога. Решается это довольно простыми [реврайтами](http://httpd.apache.org/docs/current/mod/mod_rewrite.html), не считая того, 
что отдавать нужно только файлы, которые точно лежат в кеше - иначе Rails станет получать неправильные пути и перестанет работать.

В общем, нужен вот такой [`.htaccess`](http://en.wikipedia.org/wiki/Htaccess):

public/.htaccess

RewriteEngine On

убираем слеш в конце пути

RewriteCond %{REQUEST_URI} ^([^.]+)/$ RewriteRule ^[^.]+/$ /%1 [QSA,L]

перенаправляем в кеш, только если там есть файл

RewriteCond %{THE_REQUEST} ^(GET|HEAD) RewriteCond %{DOCUMENT_ROOT}/cache/%1 -f RewriteRule ^.+$ /cache/%1 [QSA,L]

то же для страниц без расширения (к ним Rails приписывает .html)

RewriteCond %{THE_REQUEST} ^(GET|HEAD) RewriteCond %{REQUEST_URI} ^([^.]+)$ RewriteCond %{DOCUMENT_ROOT}/cache/%1.html -f RewriteRule ^[^.]+$ /cache/%1.html [QSA,L]

то же для пустого пути

RewriteCond %{THE_REQUEST} ^(GET|HEAD) RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f RewriteRule ^$ /cache/index.html [QSA,L]


или же такой конфиг для [nginx](http://nginx.org/):

nginx if ($request_method !~ ^(GET|HEAD)$) { break; }

location ^~ /cache { internal; }

if (-f $document_root/cache/index.html) { rewrite ^/$ /cache/index.html last; }

if (-f $document_root/cache/$request_uri) { rewrite .* /cache/$request_uri last; }

if (-f $document_root/cache/$request_uri.html) { rewrite .* /cache/$request_uri.html last; } ```

Очистить весь кеш можно обыкновенным rm -rf public/cache/*.

Buy me a coffee Понравился пост? Угостите кофе