よたらぼ
自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。

July 05, 2007 [おもひで]

[Rails] Ruby-GetText+Railsのキャッシュ

rubyonrails-talkでRuby-GetTextでキャッシュってどうやるの?という質問があった。そういえば、この質問、過去にも何回かあったなぁ、と思ってちょっと見てみたら、Page/Action/Fragmentの各キャッシュのうち、Action/Fragmentについてはあっさりと対応できることがわかった。具体的には以下のコードをどこかしら(プラグインやapplicaton.rbあたり)に追加すればOK。

module ActionController
  module Caching
    module Fragments
      def fragment_cache_key_with_gettext(name) 
        fragment_cache_key_without_gettext(name).gsub('?', '.').gsub(/:/, ".") << "_#{Locale.current}"
      end
      alias_method_chain :fragment_cache_key, :gettext
 
      def expire_fragment_with_gettext(name, options = nil)
        return unless perform_caching
 
        key = %r{#{fragment_cache_key_without_gettext(name).gsub('?', '.').gsub(/:/, ".")}}
        self.class.benchmark "Expired fragments matching: #{key.source}" do
          fragment_cache_store.delete_matched(key, options)
        end
      end
      alias_method_chain :expire_fragment, :gettext
    end
  end
end

上記はFragmentキャッシュの実装なんだけど、実はActionの方もこちらを呼んでるのでこれだけでよいはず。

使い方はRails本体とまったく変わらないけど軽く説明しておこう。念のため言っておくけど、この例ではArticleというモデルを利用している。あ、そうそう、init_gettextとか、Ruby-GetTextの諸々の設定は先に済ませておくように。

# app/controller/articles_controller.rb
class ArticlesController < ApplicationController
  caches_action :show   #showのアクションをキャッシュ
   :
   :
  def show
    @article = Article.find(params[:id])
  end
  #とりあえずcreate時にキャッシュをクリアする。
  def create
    @article = Article.new(params[:article])
    if @article.save
      expire_fragment(:action => "list")  #Flagmentキャッシュをクリア
      expire_action(:action => "show")   #Actionキャッシュをクリア
      :
      :
  end
# app/views/articles/list.rhtml
<h1>Listing articles</h1>
<% cache do %>   これ以降がキャッシュされる
  :
  :
<table>
  :
  :
</table>
  :
  :
<% end %>   ここまで

要はまったくGetTextを意識する必要がなく、オリジナルのRailsの意識のままで使うことが出来る。ステキ。

Pageキャッシュが最強なのは言うまでもないんだけど、こちらは難しそうなのでちょっと棚上げ。でも、Scaffold直後(+GetText化済み)の10レコードくらいのサンプルアプリケーションの一覧表示でも、Actionキャッシュは2.4倍, Fragmentキャッシュは、1.5倍程度高速化できたので、ちょっと複雑なビジネスロジック、DBアクセスがあればもっと高い効果があるはず。

思いもかけず簡単に実装できてしまったのでちょっと不安も残るけど、せっかくのなのでこの機能を次バージョンのRuby-GetTextに含める予定。

ひとまず、どなたか追試してみません?

[Rails] Ruby-GetText+Railsのキャッシュ(2)

もうちょっとだけ。キャッシュが実際に効いてるかどうかを目で見るには、キャッシュファイルが作成されたり削除されたりを確認するのが手っ取り早い。で、config/environment.rbの一番下に以下の記述を追加。

ActionController::Base.fragment_cache_store =
  ActionController::Caching::Fragments::FileStore.new("/home/mutoh/rails/cache/")

こうしておくと前述の例では以下のようなファイルが生成される。

/home/mutoh/rails/cache/
`-- localhost.3000
    |-- articles
    |   |-- list_en.cache
    |   |-- list_fr.cache
    |   |-- list_ja.cache
    |   `-- show
    |       `-- 24_ja.cache
    `-- articles_ja.cache


編集