High Performance Ruby行かなかった会議2日目

チケット持ってなくて1日目行ってないので、当然2日目も行ってません。今日はPerlを書いたり、さよならクロールを貰ったりしました。

さて、今日はRubyKaigiでHigh Performance Railsという発表があったらしいので、Rails 4でのキャッシュ(fragment_cache)の話でも書こうかと思います。既出だったらすみません…。

Cache Digests

Rails 4でもfragment_cacheの使い方は変わりません。ただCache Digestsというものが入っていて、キャッシュのキーにdigestが追加されるようになりました。
digestはテンプレートを元に作成されるので、これによりテンプレートが更新された場合にfragment cacheがヒットしなくなり、テンプレ更新時のキャッシュ削除忘れ事故がなくなるわけですね!便利!!

= cache 'aaaa' do
  %strong キャッシュして!!

こんな感じでキーを指定した場合には、"views/aaaa/1ed3444c6df4ab6dd640ab7196df711b" というようなキーでキャッシュされます。

ちなみにdigestを追加したくない場合は第二引数にskip_digest: trueを渡せば良いです。

= cache 'aaaa', skip_digest: true do
  %strong digestなんていらない!!

Rails 3でもこの機能を使いたい人はcache_digests( https://github.com/rails/cache_digests ) をインストールすれば使えます。

Sweeper追悼…

Rails 3まではキャッシュの削除にSweeperを使えば良い感じに書けたんですが、Rails 4からSweeperはなくなりました。追悼…。Observerがgemに切りだされたみたいなので、そっちに行ったっぽいです。
https://github.com/rails/rails-observers

ただ、先に紹介したCache Digestsを使うとキーにdigestが付与されるので、expire_fragmentでの削除が不可能です。(キーの指定に正規表現を使えばできるかもしれないですが…。)
じゃあモデルに変更があった時にキャッシュの削除をしたい場合どうするんだぜ?と思ったのですが、キャッシュのキーにupdated_atを含めておくと、モデルに変更があればキーが変わって問題ないっぽいです。
詳しくはこのあたり http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works

こうなるとキャッシュのお掃除をどうにかする必要があるんですが、めんどくさいのでexpireを指定して保存すると楽ですね。というわけでcache_storeをredisにします。

redis-store

cache_storeをredisにすると言ったんですが、あまりおすすめできません。
理由はredis-storeのgithub( https://github.com/jodosha/redis-store ) を見るとわかるんですが、pull requestが放置されまくり、半年間コミットもなく、依存関係があってrails 4と一緒にインストール出来ないからです。
それでも使いたい場合はforkして、こんな感じに修正すればインストール出来ます。
https://github.com/tohae/redis-store/commit/da281bad747b2f19107b802522a0881bae3d1440

今やってるRailsプロジェクトでは、セッションをredisに保存してnode.jsと良い感じに共有したかったのでredisにしたんですが、特に理由がないならmemcachedとかに保存するほうが良いと思います。この辺りもいつかブログに書きたい…。


というわけでRails 4でのキャッシュの話でした。数ヶ月前はRails 4も不安な感じありましたけど、最近は特に困らず使えてるのでさっさと上げてしまうのが良いと思います。Railsプロジェクトはバージョンアップとの戦いなので、後回しにせず早め早めにやりましょう!!1