一索

クジャクは夜にプログラミングします

kaminariをRails.cacheする方法

こばやんさんになるべくブログ書いた方がいいと言われたので書くことにしました。

kaminariのオブジェクトをキャッシュするのに以下のようなコードを書くことを考えますが、動作しません。

@items = Rails.cache.fetch("items/#{params[:page]}", expires_in: 1.hour) do
  Item.page(params[:page])
end

これはMarshal.dumpできないためで、Kaminari::PaginatableArrayを使うことがKaminari and Low Level Caching Issue ? Marshalling error, can't dump anonymous class · Issue #293 · amatsuda/kaminari · GitHubで示されていますが、これはpaginate_array() with total_count as option returns whole array for every page. · Issue #516 · amatsuda/kaminari · GitHubの修正のため動作しなくなっています。

現在、これを実現するには以下のようにpaddingを使うと良さそうです。

@items = Rails.cache.fetch("items/#{params[:page]}", expires_in: 1.hour) do
  items = Item.page(params[:page])
  Kaminari.paginate_array(items.to_a, limit: items.limit_value, offset: 0, total_count: items.total_count, padding: -items.offset_value)
end

以上です。