複数のモデルを跨いだページネーションをするgemを作った

ページネーションライブラリといえば、kaminariなどがあるんですが、
kaminariは Account.all.page(params[:page]) みたいに1つのモデルに対してのページネーションのみサポートしています。
では、(Admin.all + Account.all).page(params[:page]) みたいな2モデルでのページネーションをするにはどうすればよいでしょうか?

下記の通り回避する方法がいくつかあり、それらの選択できることに越したことはないでしょう。

  • 別々のリストにしたりUIでカバーする
  • (レコード数が少ないのであれば)すべてメモリ上に展開してeach_sliceなどを使ってページネーションする
  • ページネーションをしないで全部出しちゃう

私の場合は、メモリ上で展開していたeach_sliceページネーションの再実装を強いられており、(サーバ内での変更に留めたかったので) (Admin.all + Account.all).page(params[:page]) みたいな2モデルでのページネーションをするためのライブラリを作りました。

https://github.com/ubiregiinc/multi-model-paginator

paginator = MultiModelPaginator.new(per: 2, page: 0)
paginator.add(Account.all)
paginator.add(Admin.all)
paginator.result.map(&:class).map(&:to_s) # =>["Account", "Account"]

実装について。
#addメソッドで追加されたRelationオブジェクト毎にレコード数を求め、perpage から現在のポジションを計算して、offset句とlimit句を付与したSQLを発行しています。(日本語でOK)
詳しくはソースコードを読んでくれ!

以上。