欲しいjsonのイメージは下記の通り。
(GET /api/v1/users を想定)
{
"data": [
{
"id": "1",
"type": "user",
"attributes": {
"name": "user1",
"email": "test1@example.com"
},
{
"id": "2",
"type": "user",
"attributes": {
"name": "user2",
"email": "test2@example.com"
},
{
"id": "3",
"type": "user",
"attributes": {
"name": "user3",
"email": "test3@example.com"
},
},
"pagenation": {
"current": 1,
"previous": null,
"next": 2,
"limit_value": 3,
"pages": 2,
"count": 6
}
}
}
dataとは別に、paginationというメタデータをクライアント側に送ることで、ページネーション機能を実装してもらうことを考えています。
実装方法
kaminariの導入
gem 'kaminari'
bundle installする。
$ bundle install
これにより、ActiveRecord:Baseを継承したクラスはpageメソッドを得る。
Paginationモジュールの作成
app/controllers/concernに、pagination.rbを作成。
module Pagination
def resources_with_pagination(resources)
{
pagenation: {
current: resources.current_page,
previous: resources.prev_page,
next: resources.next_page,
limit_value: resources.limit_value,
pages: resources.total_pages,
count: resources.total_count
}
}
end
end
resourcesはUser.allのような、ActiveRecord::Relation型のデータを受け取ることを想定しています。
current_pageといったメソッドは、kaminariによって追加されたメソッドなので、github参照。
kaminari: https://github.com/kaminari/kaminari
コントローラーで組み合わせる
Paginationをincludeし、先程定義したresources_with_paginationメソッドを得る。
module Api
module V1
class UsersController < ApplicationController
include Pagenation
def index
users = User.all.page(params[:page]).per(3)
pagination = resources_with_pagination(users)
#方法は色々あるでしょうが、今回はmergeで結合。
json = USER_SERIALIZER.new(users).serializable_hash.merge(pagination)
render_200(json)
end
# ...
これで、最初に記述した形のjsonをクライアントに返すことができます。
GET api/v1/users?page=2 といった形でリクエストを送ることで、必要な部分の情報だけを得ることができるので、あとはクライアント側で調整しましょう。