Обновление 2020: active_model_serializer теперь поддерживает это из коробки, если вы используете схему json_api
, но документы также учат вас, как добавить его, если вы используете схему json
.
Документы находятся здесь: https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/howto/add_pagination_links.md
Ниже я объясню, как добиться желаемых результатов, если вы используете адаптеры json_api
или json
. Проверьте, какой из них вы используете на ActiveModelSerializers.config.adapter
.
Если вы используете адаптер JSON API (ваш ActiveModelSerializers.config.adapter = :json_api)
Ссылки на страницы будут включены в ваш ответ автоматически, если ресурс разбит на страницы и если вы используете адаптер JsonApi
.
Если вы хотите, чтобы в вашем ответе были ссылки на страницы, используйте Kaminari или WillPaginate.
Kaminari examples
#array
@posts = Kaminari.paginate_array([1, 2, 3]).page(3).per(1)
render json: @posts
#active_record
@posts = Post.page(3).per(1)
render json: @posts
WillPaginate examples
#array
@posts = [1,2,3].paginate(page: 3, per_page: 1)
render json: @posts
#active_record
@posts = Post.page(3).per_page(1)
render json: @posts
ActiveModelSerializers.config.adapter = :json_api
ex:
{
"data": [
{
"type": "articles",
"id": "3",
"attributes": {
"title": "JSON API paints my bikeshed!",
"body": "The shortest article. Ever.",
"created": "2015-05-22T14:56:29.000Z",
"updated": "2015-05-22T14:56:28.000Z"
}
}
],
"links": {
"self": "http://example.com/articles?page[number]=3&page[size]=1",
"first": "http://example.com/articles?page[number]=1&page[size]=1",
"prev": "http://example.com/articles?page[number]=2&page[size]=1",
"next": "http://example.com/articles?page[number]=4&page[size]=1",
"last": "http://example.com/articles?page[number]=13&page[size]=1"
}
}
Разбивка на страницы ActiveModelSerializers опирается на разбитую на страницы коллекцию с методами current_page
, total_pages
и size
, которые поддерживаются обоими Kaminari или WillPaginate.
Если вы используете адаптер JSON (ваш ActiveModelSerializers.config.adapter = :json)
Если вы не используете адаптер JSON
, ссылки на страницы не будут включены автоматически, но это можно сделать с помощью ключа meta
.
Добавьте этот метод в свой базовый контроллер API.
def pagination_dict(collection)
{
current_page: collection.current_page,
next_page: collection.next_page,
prev_page: collection.prev_page, # use collection.previous_page when using will_paginate
total_pages: collection.total_pages,
total_count: collection.total_count
}
end
Затем используйте его в своем методе рендеринга.
render json: posts, meta: pagination_dict(posts)
ex.
{
"posts": [
{
"id": 2,
"title": "JSON API paints my bikeshed!",
"body": "The shortest article. Ever."
}
],
"meta": {
"current_page": 3,
"next_page": 4,
"prev_page": 2,
"total_pages": 10,
"total_count": 10
}
}
Вы также можете добиться того же результата, если у вас есть вспомогательный метод, который добавляет информацию о разбиении на страницы в метатег. Например, в своем действии укажите собственный сериализатор.
render json: @posts, each_serializer: PostPreviewSerializer, meta: meta_attributes(@posts)
#expects pagination!
def meta_attributes(collection, extra_meta = {})
{
current_page: collection.current_page,
next_page: collection.next_page,
prev_page: collection.prev_page, # use collection.previous_page when using will_paginate
total_pages: collection.total_pages,
total_count: collection.total_count
}.merge(extra_meta)
end
Адаптер атрибутов
Этот адаптер не позволяет нам использовать ключ meta
, из-за чего невозможно добавить ссылки на страницы.
person
sandre89
schedule
18.04.2020