複数のモデルを跨いだページネーションをする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オブジェクト毎にレコード数を求め、per
と page
から現在のポジションを計算して、offset句とlimit句を付与したSQLを発行しています。(日本語でOK)
詳しくはソースコードを読んでくれ!
以上。
-
category:
- rails