Cache
キャッシュとは、使用頻度の高いデータを高速な記憶装置に蓄えておくことにより、いちいち低速な装置から読み出す無駄を省いて高速化すること。また、その際に使われる高速な記憶装置や、複製されたデータそのもののこと。
RailsにおけるCache
Rails3
Rails3までは以下の3つの代表的な機能を提供していた。
ページキャッシュ
レンダリングされたページのHTMLファイルをまるごとキャッシュする機能。キャッシュ化されたファイルはpublicディレクトリ以下に配置され、静的なファイルとして返す。
アクションキャッシュ
ページキャッシュは極めて高速だが、使える所が限定される。例えばbefore_filterで認証処理するアクションには適用できない。actionキャッシュはページキャッシュと似たような機能だが、before_filterの後に呼び出されるので、認証処理などの処理ができて、ページキャッシュより柔軟な対応ができる。
フラグメントキャッシュ
webページの多くは動的で、複数の部品(フラグメント)に構成される。フラグメントキャッシュは、部品ごとにキャッシングを行いキャッシングストアにデータを保存する。2回目以後のリクエストは部品をキャッシュストアから取り出す。
Rails4
Rails4ではページキャッシュとアクションキャシュを本体から取り除かれ、gem化されました。詳細はactionpack-page_cachingとactionpack-action_cachingを参考してください。
フラグメントキャッシュの使い方
- cache 'key' do
キャッシュしたい HTML文
上記のように、'key' を指定すると、その中身をキャッシュしてくれる。'key' の部分は、省略もできるし、Stringやオブジェクトも指定できる。
skip_digest: と expires_in: オプション
- cache 'key', expires_in: 1.minutes, skip_digest: true do
キャッシュしたい HTML文
-
expires_in: 1.minutes
: 有効期限を1秒 -
skip_digest: true
: デフォルトではキャッシュするHTML文を元にdigestを作成して、'key'の付与している。skip_digest: true
を付ける事でdigestをスキップできる。
キーにStringを指定した場合
- cache 'key' do
キャッシュしたい HTML文
この場合は、Stringのキーに対応した形でシンプルにHTMLがキャッシュされる。内部的に実際には使われるキーにはデフォルトだと中身のHTMLを元に作ったdigestが付与されるため、cacheしたいHTML自体が変更されれば、digestが変更され、自動でキャッシュが更新される。
キーを省略した場合
- cache do
キャッシュしたい HTML文
上記のように、キーを省略した場合は、ページのurlからキーが自動で作られる。url依存のキーなので、同じページでこの形を複数記述すると、どちらかのキャッシュが上書きされて大変なことになる。
キーにオブジェクトを指定した場合
- cache @object do
= @object.text
オブジェクトを指定した場合は、@object.cache_keyがキャッシュのキーとなる。ActiveRecordのオブジェクトの場合、IDや、updated_at を元にキーが作成されるので、オブジェクトのupdated_atが変更されると自動でキャッシュも更新される。
- cache @objects do
- @object.each do |object|
= object.text
上記のように配列にした場合は、各オブジェクトに対して cache_key が呼ばれてそれを連結したものがキャッシュのキーになる。よって配列の順番や中身が変更されればキャッシュは更新される。
Russian doll caching(ロシアンドールキャッシング)
以下のように、記事(article)に対して複数のコメント(comment)があるデータ構造の場合、ネストされたフラグメントキャッシュの内側のキャッシュ(comment)が更新されると、外側のキャッシュ(article)も更新してくれる機能。rails 4ならデフォルトで利用可能。
- cache @article do
= @article.title
= @article.text
- cache @article.comments do
- @article.comments do |comment|
= comment.text
この場合はモデル側で以下のように、モデル側にtouch: true
設定をする必要がある。
class Comment < ActiveRecord::Base
belongs_to :article, touch: true