Rails.cacheの落とし穴

はじめに

仕事で開発をしていた所、コードを動かしていてキャッシュされるべきところがキャッシュされないことがあったのでメモ。

結論

モデルをキャッシュする時、以下のようにしてもキャッシュされない。

@users = Rails.cache.fetch('user_all') do
  User.all
end

なぜか

ActiveRecord は評価を遅延させます。@users = User.allとしてもすぐにSQLが発行されることはなく@users.eachなど発行するクエリが決まった段階でクエリ発行されるわけです。

結論に書いたケースだとUser::ActiveRecord_Relationインスタンスがキャッシュに入り、インスタンスが評価された段階でSQLが発行されるため、結果としてキャッシュを使っても毎回SQLが発行されてしまうわけです。

どうればいいか

http://morizyun.github.io/blog/model-master-cache-rails-redis/index.html#Active-Record-Relation-to-a-1%E5%9B%9E%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%81%A6-%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5

上記の記事を参考にさせていただきました。 以下の用にto_aを使ってクエリを即時発行すればOK。

@users = Rails.cache.fetch('user_all') do
  User.all.to_a
end