Skip to content

Commit

Permalink
Merge pull request #2149 from mecampbellsoup/more-pagination-links-by…
Browse files Browse the repository at this point in the history
…-default

Always include self, first, last pagination links
  • Loading branch information
kurko authored Jun 14, 2017
2 parents 1539747 + 402883d commit 1e4d117
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 32 deletions.
61 changes: 40 additions & 21 deletions lib/active_model_serializers/adapter/json_api/pagination_links.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ def initialize(collection, adapter_options)
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
Please pass a ':serialization_context' option or
override CollectionSerializer#paginated? to return 'false'.
EOF
EOF
end
end

def as_json
per_page = collection.try(:per_page) || collection.try(:limit_value) || collection.size
pages_from.each_with_object({}) do |(key, value), hash|
params = query_parameters.merge(page: { number: value, size: per_page }).to_query

hash[key] = "#{url(adapter_options)}?#{params}"
end
{
self: location_url,
first: first_page_url,
prev: prev_page_url,
next: next_page_url,
last: last_page_url
}
end

protected
Expand All @@ -34,25 +35,39 @@ def as_json

private

def pages_from
return {} if collection.total_pages <= FIRST_PAGE

{}.tap do |pages|
pages[:self] = collection.current_page
def location_url
url_for_page(collection.current_page)
end

unless collection.current_page == FIRST_PAGE
pages[:first] = FIRST_PAGE
pages[:prev] = collection.current_page - FIRST_PAGE
end
def first_page_url
url_for_page(1)
end

unless collection.current_page == collection.total_pages
pages[:next] = collection.current_page + FIRST_PAGE
pages[:last] = collection.total_pages
end
def last_page_url
if collection.total_pages == 0
url_for_page(FIRST_PAGE)
else
url_for_page(collection.total_pages)
end
end

def url(options)
def prev_page_url
return nil if collection.current_page == FIRST_PAGE
url_for_page(collection.current_page - FIRST_PAGE)
end

def next_page_url
return nil if collection.total_pages == 0 || collection.current_page == collection.total_pages
url_for_page(collection.next_page)
end

def url_for_page(number)
params = query_parameters.dup
params[:page] = { size: per_page, number: number }
"#{url(adapter_options)}?#{params.to_query}"
end

def url(options = {})
@url ||= options.fetch(:links, {}).fetch(:self, nil) || request_url
end

Expand All @@ -63,6 +78,10 @@ def request_url
def query_parameters
@query_parameters ||= context.query_parameters
end

def per_page
@per_page ||= collection.try(:per_page) || collection.try(:limit_value) || collection.size
end
end
end
end
Expand Down
20 changes: 14 additions & 6 deletions test/action_controller/json_api/pagination_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ def test_render_pagination_links_with_will_paginate
assert_equal expected_links, response['links']
end

def test_render_only_last_and_next_pagination_links
def test_render_only_first_last_and_next_pagination_links
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
'prev' => nil,
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2" }
get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 } }
Expand All @@ -78,28 +80,34 @@ def test_render_pagination_links_with_kaminari
assert_equal expected_links, response['links']
end

def test_render_only_prev_and_first_pagination_links
def test_render_only_prev_first_and_last_pagination_links
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1" }
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
'next' => nil,
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
response = JSON.parse(@response.body)
assert_equal expected_links, response['links']
end

def test_render_only_last_and_next_pagination_links_with_additional_params
def test_render_only_first_last_and_next_pagination_links_with_additional_params
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
'prev' => nil,
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional" }
get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
response = JSON.parse(@response.body)
assert_equal expected_links, response['links']
end

def test_render_only_prev_and_first_pagination_links_with_additional_params
def test_render_only_prev_first_and_last_pagination_links_with_additional_params
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional",
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional" }
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional",
'next' => nil,
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional" }
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
response = JSON.parse(@response.body)
assert_equal expected_links, response['links']
Expand Down
22 changes: 17 additions & 5 deletions test/adapter/json_api/pagination_links_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ def data
}
end

def empty_collection_links
{
self: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
prev: nil,
next: nil,
last: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2"
}
end

def links
{
links: {
Expand All @@ -71,7 +81,9 @@ def last_page_links
links: {
self: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2",
first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2"
prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
next: nil,
last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2"
}
}
end
Expand Down Expand Up @@ -108,10 +120,10 @@ def expected_response_with_last_page_pagination_links
end
end

def expected_response_with_no_data_pagination_links
def expected_response_with_empty_collection_pagination_links
{}.tap do |hash|
hash[:data] = []
hash[:links] = {}
hash.merge! links: empty_collection_links
end
end

Expand Down Expand Up @@ -139,15 +151,15 @@ def test_pagination_links_when_zero_results_kaminari

adapter = load_adapter(using_kaminari(1), mock_request)

assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
end

def test_pagination_links_when_zero_results_will_paginate
@array = []

adapter = load_adapter(using_will_paginate(1), mock_request)

assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
end

def test_last_page_pagination_links_using_kaminari
Expand Down

0 comments on commit 1e4d117

Please sign in to comment.