「クレイジー」なキャッシュ

yoshitetsuの日記:acts_as_cachedを使うを参考に導入してみた。

@categories = Category.get_cache(:all) do
  Category.find(:all, :order => 'index')
end

ブロックを渡すと、ブロックの戻り値をキャッシュします。

# acts_as_cached.rb
# key はget_cacheの引数
data = block_given? ? yield : find_data(id)
set_to_cache(key, data, ttl)
return data

このとき、get_cacheの引数:allはあくまでキャッシュのキーです。
findに渡されることもなく、なんでもよいです。(たぶん)

なので、ブロックを渡すキャッシュのとき、ソートしない:allと区別できるように

@categories = Category.get_cache(:all_with_sorted) do
  Category.find(:all, :order => 'index')
end

とかやってもちゃんとキャッシュします。


ただし、多くの場合キャッシュの廃棄は(TTLもありますが)コールバックを使って

class Category < ActiveRecord::Base
  acts_as_cached
  after_save     :expire_cache  # Category.expire_cache(id)
  before_destroy :expire_cache
end

とかやってると思いますが、これでは、Category.get_cache(:all)など、キーがレコードのid以外のキャッシュは適用されません。

なので、もし、どうしても:allや、ブロックの結果をキャッシュしたいなら

class Category < ActiveRecord::Base
  acts_as_cached
  after_save     :expire_cache_by_id  # Category.expire_cache(id)
  before_destroy :expire_cache_by_id

  def self.all_with_sorted
    self.get_cache(:all_with_sorted) do
      self.find(:all, :order => 'index')
    end
  end

  def expire_cache_by_id
    expire_cache
    self.class.expire_cache(:all)
    self.class.expire_cache(:all_with_sorted)
  end
end

とかやるべきだとおもいます。