[rails]fragment cacheを使ってみる
fragment cacheを使うとテンプレートの一部を部分的にキャッシュすることが可能になります。
Rails3ではfragment cacheの他にpage cache、action cacheがありましたが、Rails4ではpage cache、action cacheが廃止になりました。
Rails3とRails4の場合でfragment cacheを使った際のメモを残しておきます。
Rails3の場合(Rails 3.2.13で確認)
例としてBookの一覧をキャッシュしたい場合を挙げます。
著者ID(author_id)とページ番号(page)毎にキャッシュできるようにしてみます。
テンプレート側では
<% cache(sprintf(Settings.cache_key.book, @author_id, @page), :expires_in => Settings.book.cache_expire) do %>
キャッシュさせたい内容
<% @books.each do |book| %>
<%= book.name %>
<% end %>
<% end %>
とすることで、cache('key') do end ブロック内がキャッシュされます。
また、:expires_in オプションで有効期限を設定できます。
コントローラ側では
class BookController < ApplicationController
def index
@author_id = params['author_id'].to_i > 0 ? params['author_id'].to_i : nil
@page = params['page'].to_i > 0 ? params['page'].to_i : 1
# キャッシュのチェック
unless fragment_exist?(sprintf(Settings.cache_key.book, @author_id, @page))
@books = Book.where(author_id: @author_id).page(@page).per(Settings.book.limit)
end
end
end
fragment_exist?で該当キーのキャッシュが存在するかをチェックし、存在しない場合はBookモデルからデータを取得するようにしています。
また、定数情報に関しては、設定ファイルに切り出しておきます。
# config/settings.yml
cache_key:
book: 'book_list_%s_%s'
book:
limit: 10
cache_expire: 60*60 # キャッシュ有効期限を1時間に設定
これで該当ページにアクセスするとキャッシュが作成されます。(デフォルトだとtmp/cache/以下にファイルとして保存されます) 開発環境でテストする場合は、config/environments/development.rb の設定を
config.action_controller.perform_caching = true
にするのをお忘れなく。
Rails4の場合(Rails4.0.0で確認)
Rails4の場合も基本的にはRails3と同じ方法ですが、キャッシュキーにdigestが自動付与されるので :skip_digest => true オプションを渡してdigestを付与しないようにしました。
テンプレート側に:skip_digest => true を設定しています。
<% cache(sprintf(Settings.cache_key.book, @author_id, @page), :expires_in => Settings.book.cache_expire, :skip_digest => true) do %>
キャッシュさせたい内容
<% @books.each do |book| %>
<%= book.name %>
<% end %>
<% end %>
コントローラ側も同様に:skip_digest => true を設定しています。
class BookController < ApplicationController
def index
@author_id = params['author_id'].to_i > 0 ? params['author_id'].to_i : nil
@page = params['page'].to_i > 0 ? params['page'].to_i : 1
# キャッシュのチェック
unless fragment_exist?(sprintf(Settings.cache_key.book, @author_id, @page), :skip_digest => true)
@books = Book.where(author_id: @author_id).page(@page).per(Settings.book.limit)
end
end
end
これでRails3と4で同様のfragment cacheが使用できました。
キャッシュ周りはきちんと使えるようになりたいです。