-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1041 from bacarini/master
Adding pagination links
- Loading branch information
Showing
13 changed files
with
614 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,4 @@ test/version_tmp | |
tmp | ||
*.swp | ||
.ruby-version | ||
.ruby-gemset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# How to add pagination links | ||
|
||
### JSON-API adapter | ||
|
||
Pagination links will be included in your response automatically as long as the resource is paginated and if you are using a ```JSON-API``` adapter. | ||
|
||
If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate). | ||
|
||
###### Kaminari examples | ||
```ruby | ||
#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 | ||
|
||
```ruby | ||
#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 | ||
``` | ||
|
||
```ruby | ||
ActiveModel::Serializer.config.adapter = :json_api | ||
``` | ||
|
||
ex: | ||
```json | ||
{ | ||
"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" | ||
} | ||
} | ||
``` | ||
|
||
AMS pagination relies on a paginated collection with the methods `current_page`, `total_pages`, and `size`, such as are supported by both [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate). | ||
|
||
|
||
### JSON adapter | ||
|
||
If you are using `JSON` adapter, pagination links will not be included automatically, but it is possible to do so using `meta` key. | ||
|
||
In your action specify a custom serializer. | ||
```ruby | ||
render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer | ||
``` | ||
|
||
And then, you could do something like the following class. | ||
```ruby | ||
class PaginatedSerializer < ActiveModel::Serializer::ArraySerializer | ||
def initialize(object, options={}) | ||
meta_key = options[:meta_key] || :meta | ||
options[meta_key] ||= {} | ||
options[meta_key] = { | ||
current_page: object.current_page, | ||
next_page: object.next_page, | ||
prev_page: object.prev_page, | ||
total_pages: object.total_pages, | ||
total_count: object.total_count | ||
} | ||
super(object, options) | ||
end | ||
end | ||
``` | ||
ex. | ||
```json | ||
{ | ||
"articles": [ | ||
{ | ||
"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 | ||
} | ||
} | ||
``` | ||
|
||
### FlattenJSON adapter | ||
|
||
This adapter does not allow us to use `meta` key, due to that it is not possible to add pagination links. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
lib/active_model/serializer/adapter/json_api/pagination_links.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
module ActiveModel | ||
class Serializer | ||
class Adapter | ||
class JsonApi < Adapter | ||
class PaginationLinks | ||
FIRST_PAGE = 1 | ||
|
||
attr_reader :collection, :context | ||
|
||
def initialize(collection, context) | ||
@collection = collection | ||
@context = context | ||
end | ||
|
||
def serializable_hash(options = {}) | ||
pages_from.each_with_object({}) do |(key, value), hash| | ||
params = query_parameters.merge(page: { number: value, size: collection.size }).to_query | ||
|
||
hash[key] = "#{url(options)}?#{params}" | ||
end | ||
end | ||
|
||
private | ||
|
||
def pages_from | ||
return {} if collection.total_pages == FIRST_PAGE | ||
|
||
{}.tap do |pages| | ||
pages[:self] = collection.current_page | ||
|
||
unless collection.current_page == FIRST_PAGE | ||
pages[:first] = FIRST_PAGE | ||
pages[:prev] = collection.current_page - FIRST_PAGE | ||
end | ||
|
||
unless collection.current_page == collection.total_pages | ||
pages[:next] = collection.current_page + FIRST_PAGE | ||
pages[:last] = collection.total_pages | ||
end | ||
end | ||
end | ||
|
||
def url(options) | ||
@url ||= options.fetch(:links, {}).fetch(:self, nil) || original_url | ||
end | ||
|
||
def original_url | ||
@original_url ||= context.original_url[/\A[^?]+/] | ||
end | ||
|
||
def query_parameters | ||
@query_parameters ||= context.query_parameters | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.