emolog

脳内メモです。

railsでいい感じにページングしたい人生だった

railsでmobile用にページングを作成する必要があり、いい感じにページングしたかったのでメモです。

要件

以下をapiのcall元(今回であれば)mobileからparameterが渡される。 それに合わせてページングする🐕

  • pagingした何ページ目か
    • page
    • defautl: 1
  • pagingの取得レコード単位
    • limit
    • defautl: 25
  • sort順(update)
    • desc
    • asc
    • defautl: asc

方針

# こんな感じで使える
User.page(ページング対象のページ番号).per(1ページの取得レコード数)
  • kaminari使っていろんなmodelを以下みたいにpagingしたい
User.paging(page: 1, limit: 20, order: "desc")

実装

  • paginate のconcernを作成
  • いろんなmodelで使うスコープなりメソッドをまとめがち

app/models/concerns/paginate.rb

# ページング用の共通部品
module Paginate
  extend ActiveSupport::Concern
  # ここでkaminari使えるように
  include Kaminari::PageScopeMethods

  # 指定がなかった場合のdefault値
  DEFAULT_ORDER = 'asc'
  DEFAULT_PAGE = 1
  DEFAULT_LIMIT = 25

  included do
    # クエリはscopeにまとめる
    scope :by_paging, -> (order, page, limit) {
      order(updated_at: order).page(page).per(limit)
    }
  end

  class_methods do
    # modelから呼ばれるメソッド
    def paging(order: nil, page: nil, limit: nil)
      # nilの場合は定数で定義しているdefault値を入れる
      order = order.nil? ? DEFAULT_ORDER : order
      page = page.nil? ? DEFAULT_PAGE : page
      limit = limit.nil? ? DEFAULT_LIMIT : limit
      by_paging(order, page, limit)
    end

  end
end
  • pagingを使いたいmodel側でincludeする
class ArticleComment < ApplicationRecord
  include Paginate
end

使ってみる

  • 指定しない場合は1ページ目の25件をASCで
164] pry(main)> ArticleComment.paging
  ArticleComment Load (0.3ms)  SELECT `article_comments`.* FROM `article_comments` ORDER BY `article_comments`.`updated_at` ASC LIMIT 25 OFFSET 0
=> [#<ArticleComment:0x00007fe50271a5b8 id: 1, user_id: 1, article_id: 48158527, theme_id: 1, content: "Corona Virus is taking over!!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>,
 #<ArticleComment:0x00007fe50271a4f0 id: 2, user_id: 2, article_id: 48158527, theme_id: 1, content: "Always wash your hands..yes you!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>,
 #<ArticleComment:0x00007fe50271a428 id: 9, user_id: 1, article_id: 48158527, theme_id: 1, content: "おけまる🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️", created_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00, updated_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00>]
[165] pry(main)> 
  • order変更(decs)
[170] pry(main)> 
[171] pry(main)> ArticleComment.paging(order: "desc")
  ArticleComment Load (0.4ms)  SELECT `article_comments`.* FROM `article_comments` ORDER BY `article_comments`.`updated_at` DESC LIMIT 25 OFFSET 0
=> [#<ArticleComment:0x00007fe50a096f68 id: 9, user_id: 1, article_id: 48158527, theme_id: 1, content: "おけまる🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️", created_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00, updated_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00>,
 #<ArticleComment:0x00007fe50a096e78 id: 2, user_id: 2, article_id: 48158527, theme_id: 1, content: "Always wash your hands..yes you!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>,
 #<ArticleComment:0x00007fe50a096d38 id: 1, user_id: 1, article_id: 48158527, theme_id: 1, content: "Corona Virus is taking over!!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>]
  • 2ページめ / ページング単位: 1 / order: desc
[187] pry(main)> 
[188] pry(main)> ArticleComment.paging(page: 2, limit: 1, order: "desc")
  ArticleComment Load (0.3ms)  SELECT `article_comments`.* FROM `article_comments` ORDER BY `article_comments`.`updated_at` DESC LIMIT 1 OFFSET 1
=> [#<ArticleComment:0x00007fe508a2f7c0 id: 2, user_id: 2, article_id: 48158527, theme_id: 1, content: "Always wash your hands..yes you!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>]
  • 全部nil(optionalパラメータが入ってない場合とからdefaultのページング)
[194] pry(main)> ArticleComment.paging(page: nil, limit: nil, order: nil)
  ArticleComment Load (0.3ms)  SELECT `article_comments`.* FROM `article_comments` ORDER BY `article_comments`.`updated_at` ASC LIMIT 25 OFFSET 0
=> [#<ArticleComment:0x00007fe50273d7e8 id: 1, user_id: 1, article_id: 48158527, theme_id: 1, content: "Corona Virus is taking over!!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>,
 #<ArticleComment:0x00007fe50273d720 id: 2, user_id: 2, article_id: 48158527, theme_id: 1, content: "Always wash your hands..yes you!", created_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00, updated_at: Thu, 16 Apr 2020 08:40:42 UTC +00:00>,
 #<ArticleComment:0x00007fe50273d658 id: 9, user_id: 1, article_id: 48158527, theme_id: 1, content: "おけまる🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️🙆<200d>♀️", created_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00, updated_at: Mon, 20 Apr 2020 01:57:23 UTC +00:00>]

おけまる🙆‍♀️🙆‍♀️ (なんかいい感じのやりかたがあれば教えて下さい)