Skip to content

Commit 1e4d117

Browse files
authored
Merge pull request #2149 from mecampbellsoup/more-pagination-links-by-default
Always include self, first, last pagination links
2 parents 1539747 + 402883d commit 1e4d117

File tree

3 files changed

+71
-32
lines changed

3 files changed

+71
-32
lines changed

lib/active_model_serializers/adapter/json_api/pagination_links.rb

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ def initialize(collection, adapter_options)
1515
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
1616
Please pass a ':serialization_context' option or
1717
override CollectionSerializer#paginated? to return 'false'.
18-
EOF
18+
EOF
1919
end
2020
end
2121

2222
def as_json
23-
per_page = collection.try(:per_page) || collection.try(:limit_value) || collection.size
24-
pages_from.each_with_object({}) do |(key, value), hash|
25-
params = query_parameters.merge(page: { number: value, size: per_page }).to_query
26-
27-
hash[key] = "#{url(adapter_options)}?#{params}"
28-
end
23+
{
24+
self: location_url,
25+
first: first_page_url,
26+
prev: prev_page_url,
27+
next: next_page_url,
28+
last: last_page_url
29+
}
2930
end
3031

3132
protected
@@ -34,25 +35,39 @@ def as_json
3435

3536
private
3637

37-
def pages_from
38-
return {} if collection.total_pages <= FIRST_PAGE
39-
40-
{}.tap do |pages|
41-
pages[:self] = collection.current_page
38+
def location_url
39+
url_for_page(collection.current_page)
40+
end
4241

43-
unless collection.current_page == FIRST_PAGE
44-
pages[:first] = FIRST_PAGE
45-
pages[:prev] = collection.current_page - FIRST_PAGE
46-
end
42+
def first_page_url
43+
url_for_page(1)
44+
end
4745

48-
unless collection.current_page == collection.total_pages
49-
pages[:next] = collection.current_page + FIRST_PAGE
50-
pages[:last] = collection.total_pages
51-
end
46+
def last_page_url
47+
if collection.total_pages == 0
48+
url_for_page(FIRST_PAGE)
49+
else
50+
url_for_page(collection.total_pages)
5251
end
5352
end
5453

55-
def url(options)
54+
def prev_page_url
55+
return nil if collection.current_page == FIRST_PAGE
56+
url_for_page(collection.current_page - FIRST_PAGE)
57+
end
58+
59+
def next_page_url
60+
return nil if collection.total_pages == 0 || collection.current_page == collection.total_pages
61+
url_for_page(collection.next_page)
62+
end
63+
64+
def url_for_page(number)
65+
params = query_parameters.dup
66+
params[:page] = { size: per_page, number: number }
67+
"#{url(adapter_options)}?#{params.to_query}"
68+
end
69+
70+
def url(options = {})
5671
@url ||= options.fetch(:links, {}).fetch(:self, nil) || request_url
5772
end
5873

@@ -63,6 +78,10 @@ def request_url
6378
def query_parameters
6479
@query_parameters ||= context.query_parameters
6580
end
81+
82+
def per_page
83+
@per_page ||= collection.try(:per_page) || collection.try(:limit_value) || collection.size
84+
end
6685
end
6786
end
6887
end

test/action_controller/json_api/pagination_test.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ def test_render_pagination_links_with_will_paginate
5858
assert_equal expected_links, response['links']
5959
end
6060

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

81-
def test_render_only_prev_and_first_pagination_links
83+
def test_render_only_prev_first_and_last_pagination_links
8284
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
8385
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
84-
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1" }
86+
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
87+
'next' => nil,
88+
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
8589
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
8690
response = JSON.parse(@response.body)
8791
assert_equal expected_links, response['links']
8892
end
8993

90-
def test_render_only_last_and_next_pagination_links_with_additional_params
94+
def test_render_only_first_last_and_next_pagination_links_with_additional_params
9195
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
96+
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
97+
'prev' => nil,
9298
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
9399
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional" }
94100
get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
95101
response = JSON.parse(@response.body)
96102
assert_equal expected_links, response['links']
97103
end
98104

99-
def test_render_only_prev_and_first_pagination_links_with_additional_params
105+
def test_render_only_prev_first_and_last_pagination_links_with_additional_params
100106
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional",
101107
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
102-
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional" }
108+
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional",
109+
'next' => nil,
110+
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional" }
103111
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
104112
response = JSON.parse(@response.body)
105113
assert_equal expected_links, response['links']

test/adapter/json_api/pagination_links_test.rb

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ def data
5454
}
5555
end
5656

57+
def empty_collection_links
58+
{
59+
self: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
60+
first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
61+
prev: nil,
62+
next: nil,
63+
last: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2"
64+
}
65+
end
66+
5767
def links
5868
{
5969
links: {
@@ -71,7 +81,9 @@ def last_page_links
7181
links: {
7282
self: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2",
7383
first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
74-
prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2"
84+
prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
85+
next: nil,
86+
last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2"
7587
}
7688
}
7789
end
@@ -108,10 +120,10 @@ def expected_response_with_last_page_pagination_links
108120
end
109121
end
110122

111-
def expected_response_with_no_data_pagination_links
123+
def expected_response_with_empty_collection_pagination_links
112124
{}.tap do |hash|
113125
hash[:data] = []
114-
hash[:links] = {}
126+
hash.merge! links: empty_collection_links
115127
end
116128
end
117129

@@ -139,15 +151,15 @@ def test_pagination_links_when_zero_results_kaminari
139151

140152
adapter = load_adapter(using_kaminari(1), mock_request)
141153

142-
assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
154+
assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
143155
end
144156

145157
def test_pagination_links_when_zero_results_will_paginate
146158
@array = []
147159

148160
adapter = load_adapter(using_will_paginate(1), mock_request)
149161

150-
assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
162+
assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
151163
end
152164

153165
def test_last_page_pagination_links_using_kaminari

0 commit comments

Comments
 (0)