acts_as_cachedを使う
ActiveRecord をキャッシュしたい、そんなあなたに acts_as_cached。
1. Install memcached.
http://www.danga.com/memcached/download.bml
より memcached の最新版をインストール。
途中、libevent が必要だったので、こっちを先にインストールしておく。
2. Install memcache-client.
$ sudo gem install memcache-client
参考にしたドキュメントには memcached-client って書いてあったけど、これ間違い。d いらない!
3. Install this plugin.
$ cd RAILS_ROOT $ ruby script/plugin install svn://errtheblog.com/svn/plugins/acts_as_cached $ mv vendor/plugins/acts_as_cached/memcached.yml.default config/memcached.yml
memcached.yml を使用環境に合わせて適当に編集。
cached-model は environment.rb に記述しないといけなかったけど、acts_as_cached は yml。素晴らしい。
ちなみに、デフォルトは以下のようになっている。
defaults: ttl: 1800 readonly: false urlencode: false c_threshold: 10000 compression: true debug: false namespace: app sessions: false fragments: false servers: localhost:11211 benchmarking: true development: sessions: false fragments: false servers: localhost:11211 # turn off caching test: disabled: true production: benchmarking: false servers: - 192.185.254.121:11211 - 192.185.254.138:11211 - 192.185.254.160:11211
5. Start rails. Enjoy.
基本
class Story < ActiveRecord::Base acts_as_cached end
これで、acts_as_cachedのさまざまなメソッドが利用できる。
キャッシュを得たい場合、get_cache を使う。
>> Story.get_cache(1) => #<Story:0x29761bc...>
キャッシュを消したい場合、expire_cache を使う。
>> Story.expire_cache(10002) => "DELETED\r\n"
メソッド
Class methods:
- get_cache(id)
すでにキャッシュが作られてた場合、何もしない。そうではない場合、find(id) を call し、結果をキャッシュする。
- expire_cache(id)
キャッシュをクリアする。
- reset_cache(id)
キャッシュをリセットする。
Instance methods:
- expire_cache, reset_cache
story.expire_cache は Story.expire_cache(story_object.id) と同じ。
生存時間
デフォルトのキャッシュ生存時間は30分だけど、指定も可能。
class Story < ActiveRecord::Base acts_as_cached def self.ttl 20.minutes end end
コールバック
コールバックを使用できる。
class Story < ActiveRecord::Base acts_as_cached after_save :expire_cache_by_id before_destroy :expire_cache_by_id end
例では、save の後、destroy の前にコールバックを用いてキャッシュをクリアしている。
Conditions
ここからが acts_as_cached の本領発揮。
find の際に conditions が使える。
class Story < ActiveRecord::Base acts_as_cached :conditions => ['stories.state = ?', Story::State::Published] end
Story.get_cache(1) を呼んだ際、
Story.find(1, :conditions => ['stories.state = ?', Story::State::Published])
に展開される!
ページロードしたときすべてのキャッシュをクリア
acts_as_cached model は skip_cache_gets っていう setter があって、新しいデータがいつでも得たいとき、キャッシュしない設定ができる。
class ApplicationController < ActionController::Base before_filter :check_cache_skip def check_cache_skip returning true do ActiveRecord::Base.skip_cache_gets = params[:skip_cache] ? true : false end end end
?skip_cache=1 のパラメータ付きで呼ばれたらキャッシュしていないデータが得られる。
Associations
なんと、asssociation まで使える。というか、これを使うための、acts_as_memcached。
class Story < ActiveRecord::Base acts_as_cached :include => [ :pages, :category ] end
Story.get_cache(1) を呼んだとき、
Story.find(1, :include => [ :pages, :category ])
に展開される。
Story と assosiation している Author があったとして、Author側もキャッシュしたものを得たいとき。
class Story < ActiveRecord::Base acts_as_cached :include => :author def after_save expire_cache(id) Author.expire_cache(author_id) end end class Author < ActiveRecord::Base acts_as_cached def after_save expire_cache(id) stories.each do |story| Story.expire_cache(story.id) end end end
と書けるけど、効率悪いので、accesor methods を オーバーライドして
class Story < ActiveRecord::Base acts_as_cached :include => :author def author Author.get_cache(author_id) end end
こんな感じにかっこよく書ける。
ブロックを渡す
実はブロックも渡せる。
@songs = Song.get_cache(:all) do Song.find(:all).to_json end
クレイジーらしいが。
さらに詳しい使い方は、ドキュメントを参照。
日本語にしてみただけではあんまりなので、自分でもいろいろ試してみよう。
参考:http://require.errtheblog.com/filedetails.php?repname=plugins&path=%2Facts_as_cached%2FREADME
acts_as_cached: ActiveRecordを手軽にキャッシュ