Skip to content

Commit 8ac47d2

Browse files
committed
Merge pull request #622 from utilityboy/page-count-meta
Meta: page_count
2 parents 174bd2f + 9c80438 commit 8ac47d2

8 files changed

Lines changed: 93 additions & 2 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,10 @@ JSONAPI.configure do |config|
18771877
config.top_level_meta_include_record_count = false
18781878
config.top_level_meta_record_count_key = :record_count
18791879
1880+
# For :paged paginators, the following are also available
1881+
config.top_level_meta_include_page_count = false
1882+
config.top_level_meta_page_count_key = :page_count
1883+
18801884
config.use_text_errors = false
18811885
18821886
# List of classes that should not be rescued by the operations processor.

lib/jsonapi/configuration.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class Configuration
2020
:top_level_links_include_pagination,
2121
:top_level_meta_include_record_count,
2222
:top_level_meta_record_count_key,
23+
:top_level_meta_include_page_count,
24+
:top_level_meta_page_count_key,
2325
:exception_class_whitelist,
2426
:always_include_to_one_linkage_data,
2527
:always_include_to_many_linkage_data,
@@ -59,6 +61,9 @@ def initialize
5961
self.top_level_meta_include_record_count = false
6062
self.top_level_meta_record_count_key = :record_count
6163

64+
self.top_level_meta_include_page_count = false
65+
self.top_level_meta_page_count_key = :page_count
66+
6267
self.use_text_errors = false
6368

6469
# List of classes that should not be rescued by the operations processor.
@@ -164,6 +169,10 @@ def exception_class_whitelisted?(e)
164169

165170
attr_writer :top_level_meta_record_count_key
166171

172+
attr_writer :top_level_meta_include_page_count
173+
174+
attr_writer :top_level_meta_page_count_key
175+
167176
attr_writer :exception_class_whitelist
168177

169178
attr_writer :always_include_to_one_linkage_data

lib/jsonapi/operation.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ def record_count
3131
include_directives: @include_directives)
3232
end
3333

34+
def page_count
35+
if @paginator.is_a?(PagedPaginator)
36+
@_page_count ||= @paginator.calculate_page_count(record_count)
37+
end
38+
end
39+
3440
def pagination_params
3541
if @paginator && JSONAPI.configuration.top_level_links_include_pagination
3642
options = {}
@@ -57,6 +63,10 @@ def apply
5763
options[:record_count] = record_count
5864
end
5965

66+
if JSONAPI.configuration.top_level_meta_include_page_count
67+
options[:page_count] = page_count
68+
end
69+
6070
return JSONAPI::ResourcesOperationResult.new(:ok,
6171
resource_records,
6272
options)
@@ -153,6 +163,12 @@ def record_count
153163
@_record_count ||= records.count(:all)
154164
end
155165

166+
def page_count
167+
if @paginator.is_a?(PagedPaginator)
168+
@_page_count ||= @paginator.calculate_page_count(record_count)
169+
end
170+
end
171+
156172
def source_resource
157173
@_source_resource ||= @source_klass.find_by_key(@source_id, context: @context)
158174
end
@@ -176,6 +192,7 @@ def options
176192
opts = {}
177193
opts.merge!(pagination_params: pagination_params) if JSONAPI.configuration.top_level_links_include_pagination
178194
opts.merge!(record_count: record_count) if JSONAPI.configuration.top_level_meta_include_record_count
195+
opts.merge!(page_count: page_count) if JSONAPI.configuration.top_level_meta_include_page_count
179196
opts
180197
end
181198

lib/jsonapi/operation_result.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ def initialize(code, resource, options = {})
3232
end
3333

3434
class ResourcesOperationResult < OperationResult
35-
attr_accessor :resources, :pagination_params, :record_count
35+
attr_accessor :resources, :pagination_params, :record_count, :page_count
3636

3737
def initialize(code, resources, options = {})
3838
@resources = resources
3939
@pagination_params = options.fetch(:pagination_params, {})
4040
@record_count = options[:record_count]
41+
@page_count = options[:page_count]
4142
super(code, options)
4243
end
4344
end

lib/jsonapi/paginator.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,18 @@ def self.requires_record_count
131131
true
132132
end
133133

134+
def calculate_page_count(record_count)
135+
(record_count / @size.to_f).ceil
136+
end
137+
134138
def apply(relation, _order_options)
135139
offset = (@number - 1) * @size
136140
relation.offset(offset).limit(@size)
137141
end
138142

139143
def links_page_params(options = {})
140144
record_count = options[:record_count]
141-
page_count = (record_count / @size.to_f).ceil
145+
page_count = calculate_page_count(record_count)
142146

143147
links_page_params = {}
144148

lib/jsonapi/response_document.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ def top_level_meta
5454
if JSONAPI.configuration.top_level_meta_include_record_count && result.respond_to?(:record_count)
5555
meta[JSONAPI.configuration.top_level_meta_record_count_key] = result.record_count
5656
end
57+
58+
if JSONAPI.configuration.top_level_meta_include_page_count && result.respond_to?(:page_count)
59+
meta[JSONAPI.configuration.top_level_meta_page_count_key] = result.page_count
60+
end
5761
end
5862

5963
meta.deep_transform_keys { |key| @key_formatter.format(key) }

test/controllers/controller_test.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,15 @@ def test_show_does_not_include_records_count_in_meta
367367
JSONAPI.configuration.top_level_meta_include_record_count = false
368368
end
369369

370+
def test_show_does_not_include_pages_count_in_meta
371+
JSONAPI.configuration.top_level_meta_include_page_count = true
372+
get :show, { id: Post.first.id }
373+
assert_response :success
374+
assert_equal json_response['meta'], nil
375+
ensure
376+
JSONAPI.configuration.top_level_meta_include_page_count = false
377+
end
378+
370379
def test_show_single_with_includes
371380
get :show, params: {id: '1', include: 'comments'}
372381
assert_response :success
@@ -2678,6 +2687,18 @@ def test_books_record_count_in_meta
26782687
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
26792688
end
26802689

2690+
def test_books_page_count_in_meta
2691+
Api::V2::BookResource.paginator :paged
2692+
JSONAPI.configuration.top_level_meta_include_page_count = true
2693+
get :index, params: {include: 'book-comments'}
2694+
JSONAPI.configuration.top_level_meta_include_page_count = false
2695+
2696+
assert_response :success
2697+
assert_equal 91, json_response['meta']['page-count']
2698+
assert_equal 10, json_response['data'].size
2699+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2700+
end
2701+
26812702
def test_books_record_count_in_meta_custom_name
26822703
Api::V2::BookResource.paginator :offset
26832704
JSONAPI.configuration.top_level_meta_include_record_count = true
@@ -2693,6 +2714,21 @@ def test_books_record_count_in_meta_custom_name
26932714
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
26942715
end
26952716

2717+
def test_books_page_count_in_meta_custom_name
2718+
Api::V2::BookResource.paginator :paged
2719+
JSONAPI.configuration.top_level_meta_include_page_count = true
2720+
JSONAPI.configuration.top_level_meta_page_count_key = 'total_pages'
2721+
2722+
get :index, params: {include: 'book-comments'}
2723+
JSONAPI.configuration.top_level_meta_include_page_count = false
2724+
JSONAPI.configuration.top_level_meta_page_count_key = :page_count
2725+
2726+
assert_response :success
2727+
assert_equal 91, json_response['meta']['total-pages']
2728+
assert_equal 10, json_response['data'].size
2729+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2730+
end
2731+
26962732
def test_books_offset_pagination_no_params_includes_query_count_one_level
26972733
Api::V2::BookResource.paginator :offset
26982734

test/integration/requests/request_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,22 @@ def test_filter_related_resources
477477
JSONAPI.configuration.top_level_meta_include_record_count = false
478478
end
479479

480+
def test_page_count_meta
481+
Api::V2::BookCommentResource.paginator :paged
482+
JSONAPI.configuration.top_level_meta_include_record_count = true
483+
JSONAPI.configuration.top_level_meta_include_page_count = true
484+
get '/api/v2/books/1/book_comments'
485+
assert_equal 26, json_response['meta']['record_count']
486+
# based on default page size
487+
assert_equal 3, json_response['meta']['page_count']
488+
get '/api/v2/books/1/book_comments?page[size]=5'
489+
assert_equal 26, json_response['meta']['record_count']
490+
assert_equal 6, json_response['meta']['page_count']
491+
ensure
492+
JSONAPI.configuration.top_level_meta_include_record_count = false
493+
JSONAPI.configuration.top_level_meta_include_page_count = false
494+
end
495+
480496
def test_pagination_related_resources_without_related
481497
Api::V2::BookResource.paginator :offset
482498
Api::V2::BookCommentResource.paginator :offset

0 commit comments

Comments
 (0)