Add pagination links automatically

Pagination links will be included in your response automatically as long
as the resource is paginated using Kaminari or WillPaginate
and if you are using a JSON-API adapter. The others adapters does not have this feature.
This commit is contained in:
Bruno Bacarini 2015-08-17 14:25:59 -03:00
parent a41d90cce4
commit 2c2f948fa0
8 changed files with 52 additions and 47 deletions

View File

@ -118,7 +118,7 @@ If you wish to use a serializer other than the default, you can explicitly pass
render json: @posts, each_serializer: PostPreviewSerializer
# Or, you can explicitly provide the collection serializer as well
render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer
render json: @posts, serializer: CollectionSerializer, each_serializer: PostPreviewSerializer
```
### Meta
@ -272,6 +272,11 @@ And you can change the JSON key that the serializer should use for a particular
The `url` declaration describes which named routes to use while generating URLs
for your JSON. Not every adapter will require URLs.
## Pagination
Pagination links will be included in your response automatically as long as the resource is paginated using [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate) and if you are using a ```JSON-API``` adapter. The others adapters does not have this feature.
For more information about it, please see in our docs [How to add pagination links](https://github.com/rails-api/active_model_serializers/blob/master/docs/howto/add_pagination_links.md)
## Caching

View File

@ -1,15 +1,19 @@
# How to add pagination links
If you want pagination links in your response, specify it in the `render`
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. The others adapters does not have this feature.
If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate).
```ruby
render json: @posts, pagination: true
#kaminari example
@posts = Kaminari.paginate_array(Post.all).page(3).per(1)
render json: @posts
#will_paginate example
@posts = Post.all.paginate(page: 3, per_page: 1)
render json: @posts
```
AMS relies on either `Kaminari` or `WillPaginate`. Please install either dependency by adding one of those to your Gemfile.
Pagination links will only be included in your response if you are using a ```JSON-API``` adapter, the others adapters doesn't have this feature.
```ruby
ActiveModel::Serializer.config.adapter = :json_api
```
@ -38,3 +42,5 @@ ex:
}
}
```
AMS relies on either [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate). Please install either dependency by adding one of those to your Gemfile.

View File

@ -25,9 +25,10 @@ module ActionController
"Please pass 'adapter: false' or see ActiveSupport::SerializableResource#serialize"
options[:adapter] = false
end
if options[:pagination]
options[:original_url] = original_url
options[:query_parameters] = query_parameters
if resource.respond_to?(:current_page) && resource.respond_to?(:total_pages)
options[:pagination] = {}
options[:pagination][:original_url] = original_url
options[:pagination][:query_parameters] = query_parameters
end
ActiveModel::SerializableResource.serialize(resource, options) do |serializable_resource|
if serializable_resource.serializer?

View File

@ -2,7 +2,7 @@ require "set"
module ActiveModel
class SerializableResource
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :pagination])
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter])
def initialize(resource, options = {})
@resource = resource

View File

@ -164,7 +164,7 @@ module ActiveModel
def add_links(options)
links = @hash.fetch(:links) { {} }
resources = serializer.instance_variable_get(:@resource)
@hash[:links] = add_pagination_links(links, resources, options) if @options[:pagination]
@hash[:links] = add_pagination_links(links, resources, options) if options[:pagination]
end
def add_pagination_links(links, resources, options)

View File

@ -14,7 +14,7 @@ module ActiveModel
def serializable_hash(options = {})
pages_from.each_with_object({}) do |(key, value), hash|
query_parameters = options.fetch(:query_parameters) { {} }
query_parameters = options[:pagination].fetch(:query_parameters) { {} }
params = query_parameters.merge(page: { number: value, size: collection.size }).to_query
hash[key] = "#{url(options)}?#{params}"
@ -51,7 +51,7 @@ module ActiveModel
def url(options)
self_link = options.fetch(:links) {{}}
self_link.fetch(:self) {} ? options[:links][:self] : options[:original_url]
self_link.fetch(:self) {} ? options[:links][:self] : options[:pagination][:original_url]
end
end
end

View File

@ -31,19 +31,16 @@ module ActionController
end
def render_pagination_using_kaminari
render json: using_kaminari, adapter: :json_api, pagination: true
render json: using_kaminari, adapter: :json_api
end
def render_pagination_using_will_paginate
render json: using_will_paginate, adapter: :json_api, pagination: true
render json: using_will_paginate, adapter: :json_api
end
def render_array_without_pagination_links
render json: using_will_paginate, adapter: :json_api, pagination: false
end
def render_array_omitting_pagination_options
render json: using_kaminari, adapter: :json_api
setup
render json: @array, adapter: :json_api
end
end
@ -104,12 +101,6 @@ module ActionController
response = JSON.parse(@response.body)
refute response.key? 'links'
end
def test_array_omitting_pagination_options
get :render_array_omitting_pagination_options, page: { number: 2, size: 1 }
response = JSON.parse(@response.body)
refute response.key? 'links'
end
end
end
end

View File

@ -27,15 +27,11 @@ module ActiveModel
end
def data
{
data: [{
id:"2",
type:"profiles",
attributes:{
name:"Name 2",
description:"Description 2"
}
}]
{ data:[
{ id:"1", type:"profiles", attributes:{name:"Name 1", description:"Description 1" } },
{ id:"2", type:"profiles", attributes:{name:"Name 2", description:"Description 2" } },
{ id:"3", type:"profiles", attributes:{name:"Name 3", description:"Description 3" } }
]
}
end
@ -56,42 +52,48 @@ module ActiveModel
end
def expected_response_with_pagination_links
data.merge links
{}.tap do |hash|
hash[:data] = [data.values.flatten.second]
hash.merge! links
end
end
def expected_response_with_pagination_links_and_additional_params
new_links = links[:links].each_with_object({}) {|(key, value), hash| hash[key] = "#{value}&teste=teste" }
data.merge links: new_links
{}.tap do |hash|
hash[:data] = [data.values.flatten.second]
hash.merge! links: new_links
end
end
def test_pagination_links_using_kaminari
serializer = ArraySerializer.new(using_kaminari)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, pagination: true)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal expected_response_with_pagination_links,
adapter.serializable_hash(original_url: "http://example.com")
adapter.serializable_hash(pagination: { original_url: "http://example.com" })
end
def test_pagination_links_using_will_paginate
serializer = ArraySerializer.new(using_will_paginate)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, pagination: true)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal expected_response_with_pagination_links,
adapter.serializable_hash(original_url: "http://example.com")
adapter.serializable_hash(pagination: { original_url: "http://example.com" })
end
def test_pagination_links_with_additional_params
serializer = ArraySerializer.new(using_will_paginate)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, pagination: true)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal expected_response_with_pagination_links_and_additional_params,
adapter.serializable_hash(original_url: "http://example.com",
query_parameters: { teste: "teste"})
adapter.serializable_hash(pagination: { original_url: "http://example.com",
query_parameters: { teste: "teste"}})
end
def test_not_showing_pagination_links
serializer = ArraySerializer.new(using_will_paginate)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, pagination: false)
serializer = ArraySerializer.new(@array)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal expected_response_without_pagination_links, adapter.serializable_hash
end