From 3db8260978119ac278d2db92b17a2611c36d754a Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Wed, 17 Feb 2016 16:30:09 -0500 Subject: [PATCH 1/7] feat(pagination): add config support for page_count meta --- lib/jsonapi/configuration.rb | 9 +++++++++ lib/jsonapi/response_document.rb | 4 ++++ test/controllers/controller_test.rb | 9 +++++++++ 3 files changed, 22 insertions(+) diff --git a/lib/jsonapi/configuration.rb b/lib/jsonapi/configuration.rb index 4cf2f0c7d..fba5c301e 100644 --- a/lib/jsonapi/configuration.rb +++ b/lib/jsonapi/configuration.rb @@ -21,6 +21,8 @@ class Configuration :top_level_links_include_pagination, :top_level_meta_include_record_count, :top_level_meta_record_count_key, + :top_level_meta_include_page_count, + :top_level_meta_page_count_key, :exception_class_whitelist, :always_include_to_one_linkage_data, :always_include_to_many_linkage_data @@ -59,6 +61,9 @@ def initialize self.top_level_meta_include_record_count = false self.top_level_meta_record_count_key = :record_count + self.top_level_meta_include_page_count = false + self.top_level_meta_page_count_key = :page_count + self.use_text_errors = false # List of classes that should not be rescued by the operations processor. @@ -111,6 +116,10 @@ def operations_processor=(operations_processor) attr_writer :top_level_meta_record_count_key + attr_writer :top_level_meta_include_page_count + + attr_writer :top_level_meta_page_count_key + attr_writer :exception_class_whitelist attr_writer :always_include_to_one_linkage_data diff --git a/lib/jsonapi/response_document.rb b/lib/jsonapi/response_document.rb index 19a75acba..3d1381943 100644 --- a/lib/jsonapi/response_document.rb +++ b/lib/jsonapi/response_document.rb @@ -54,6 +54,10 @@ def top_level_meta if JSONAPI.configuration.top_level_meta_include_record_count && result.respond_to?(:record_count) meta[JSONAPI.configuration.top_level_meta_record_count_key] = result.record_count end + + if JSONAPI.configuration.top_level_meta_include_page_count && result.respond_to?(:page_count) + meta[JSONAPI.configuration.top_level_meta_page_count_key] = result.page_count + end end meta.deep_transform_keys { |key| @key_formatter.format(key) } diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index 1fcd0d883..099b7cfa6 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -335,6 +335,15 @@ def test_show_does_not_include_records_count_in_meta JSONAPI.configuration.top_level_meta_include_record_count = false end + def test_show_does_not_include_pages_count_in_meta + JSONAPI.configuration.top_level_meta_include_page_count = true + get :show, { id: Post.first.id } + assert_response :success + assert_equal json_response['meta'], nil + ensure + JSONAPI.configuration.top_level_meta_include_page_count = false + end + def test_show_single_with_includes get :show, {id: '1', include: 'comments'} assert_response :success From 9e666d90535ba26d7d020c40115ec75cfb906bca Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Wed, 17 Feb 2016 17:46:19 -0500 Subject: [PATCH 2/7] refactor(pagination): extract page_count calculation into an instance method --- lib/jsonapi/paginator.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/jsonapi/paginator.rb b/lib/jsonapi/paginator.rb index e21f97f2e..3ad00abbe 100644 --- a/lib/jsonapi/paginator.rb +++ b/lib/jsonapi/paginator.rb @@ -131,6 +131,10 @@ def self.requires_record_count true end + def calculate_page_count(record_count) + (record_count / @size.to_f).ceil + end + def apply(relation, _order_options) offset = (@number - 1) * @size relation.offset(offset).limit(@size) @@ -138,7 +142,7 @@ def apply(relation, _order_options) def links_page_params(options = {}) record_count = options[:record_count] - page_count = (record_count / @size.to_f).ceil + page_count = calculate_page_count(record_count) links_page_params = {} From 80e136e9f59047b65e105988dc852ee052083841 Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Wed, 17 Feb 2016 17:46:46 -0500 Subject: [PATCH 3/7] feat(pagination): return meta `page_count` for paged paginators --- lib/jsonapi/operation.rb | 11 +++++++++++ lib/jsonapi/operation_result.rb | 3 ++- test/integration/requests/request_test.rb | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/jsonapi/operation.rb b/lib/jsonapi/operation.rb index 9d8859b82..407a76016 100644 --- a/lib/jsonapi/operation.rb +++ b/lib/jsonapi/operation.rb @@ -57,6 +57,10 @@ def apply options[:record_count] = record_count end + if JSONAPI.configuration.top_level_meta_include_page_count + options[:page_count] = page_count + end + return JSONAPI::ResourcesOperationResult.new(:ok, resource_records, options) @@ -153,6 +157,12 @@ def record_count @_record_count ||= records.count(:all) end + def page_count + if @paginator.is_a?(PagedPaginator) + @_page_count ||= @paginator.calculate_page_count(record_count) + end + end + def source_resource @_source_resource ||= @source_klass.find_by_key(@source_id, context: @context) end @@ -176,6 +186,7 @@ def options opts = {} opts.merge!(pagination_params: pagination_params) if JSONAPI.configuration.top_level_links_include_pagination opts.merge!(record_count: record_count) if JSONAPI.configuration.top_level_meta_include_record_count + opts.merge!(page_count: page_count) if JSONAPI.configuration.top_level_meta_include_page_count opts end diff --git a/lib/jsonapi/operation_result.rb b/lib/jsonapi/operation_result.rb index a01361cad..43e996a15 100644 --- a/lib/jsonapi/operation_result.rb +++ b/lib/jsonapi/operation_result.rb @@ -32,12 +32,13 @@ def initialize(code, resource, options = {}) end class ResourcesOperationResult < OperationResult - attr_accessor :resources, :pagination_params, :record_count + attr_accessor :resources, :pagination_params, :record_count, :page_count def initialize(code, resources, options = {}) @resources = resources @pagination_params = options.fetch(:pagination_params, {}) @record_count = options[:record_count] + @page_count = options[:page_count] super(code, options) end end diff --git a/test/integration/requests/request_test.rb b/test/integration/requests/request_test.rb index 2e603ed7d..681b9e7ce 100644 --- a/test/integration/requests/request_test.rb +++ b/test/integration/requests/request_test.rb @@ -442,6 +442,22 @@ def test_filter_related_resources JSONAPI.configuration.top_level_meta_include_record_count = false end + def test_page_count_meta + Api::V2::BookCommentResource.paginator :paged + JSONAPI.configuration.top_level_meta_include_record_count = true + JSONAPI.configuration.top_level_meta_include_page_count = true + get '/api/v2/books/1/book_comments' + assert_equal 26, json_response['meta']['record_count'] + # based on default page size + assert_equal 3, json_response['meta']['page_count'] + get '/api/v2/books/1/book_comments?page[size]=5' + assert_equal 26, json_response['meta']['record_count'] + assert_equal 6, json_response['meta']['page_count'] + ensure + JSONAPI.configuration.top_level_meta_include_record_count = false + JSONAPI.configuration.top_level_meta_include_page_count = false + end + def test_pagination_related_resources_without_related Api::V2::BookResource.paginator :offset Api::V2::BookCommentResource.paginator :offset From 9d15112fa198c5a6fd1f78715a30747deb98ad44 Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Wed, 17 Feb 2016 18:14:59 -0500 Subject: [PATCH 4/7] fix(pagination): add page_count for FindOperation --- lib/jsonapi/operation.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/jsonapi/operation.rb b/lib/jsonapi/operation.rb index 407a76016..f51307139 100644 --- a/lib/jsonapi/operation.rb +++ b/lib/jsonapi/operation.rb @@ -31,6 +31,12 @@ def record_count include_directives: @include_directives) end + def page_count + if @paginator.is_a?(PagedPaginator) + @_page_count ||= @paginator.calculate_page_count(record_count) + end + end + def pagination_params if @paginator && JSONAPI.configuration.top_level_links_include_pagination options = {} From 489cdbdb517f8830a0ea1ff4523d6160dabb2de3 Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Tue, 3 May 2016 20:43:50 -0400 Subject: [PATCH 5/7] test(controller): add test for page_count in meta --- test/controllers/controller_test.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index f235f30d2..95891b2e2 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -2687,6 +2687,21 @@ def test_books_record_count_in_meta assert_equal 'Book 0', json_response['data'][0]['attributes']['title'] end + def test_books_page_count_in_meta + Api::V2::BookResource.paginator :paged + JSONAPI.configuration.top_level_meta_include_record_count = true + JSONAPI.configuration.top_level_meta_include_page_count = true + get :index, params: {include: 'book-comments'} + JSONAPI.configuration.top_level_meta_include_record_count = false + JSONAPI.configuration.top_level_meta_include_page_count = false + + assert_response :success + assert_equal 901, json_response['meta']['record-count'] + assert_equal 91, json_response['meta']['page-count'] + assert_equal 10, json_response['data'].size + assert_equal 'Book 0', json_response['data'][0]['attributes']['title'] + end + def test_books_record_count_in_meta_custom_name Api::V2::BookResource.paginator :offset JSONAPI.configuration.top_level_meta_include_record_count = true From 14bb1fcab14e7c42e0b4b2d6394083604f8817dc Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Tue, 3 May 2016 20:52:27 -0400 Subject: [PATCH 6/7] test(controller): test custom page_count meta name --- test/controllers/controller_test.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index 95891b2e2..6898a38dc 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -2689,14 +2689,11 @@ def test_books_record_count_in_meta def test_books_page_count_in_meta Api::V2::BookResource.paginator :paged - JSONAPI.configuration.top_level_meta_include_record_count = true JSONAPI.configuration.top_level_meta_include_page_count = true get :index, params: {include: 'book-comments'} - JSONAPI.configuration.top_level_meta_include_record_count = false JSONAPI.configuration.top_level_meta_include_page_count = false assert_response :success - assert_equal 901, json_response['meta']['record-count'] assert_equal 91, json_response['meta']['page-count'] assert_equal 10, json_response['data'].size assert_equal 'Book 0', json_response['data'][0]['attributes']['title'] @@ -2717,6 +2714,21 @@ def test_books_record_count_in_meta_custom_name assert_equal 'Book 0', json_response['data'][0]['attributes']['title'] end + def test_books_page_count_in_meta_custom_name + Api::V2::BookResource.paginator :paged + JSONAPI.configuration.top_level_meta_include_page_count = true + JSONAPI.configuration.top_level_meta_page_count_key = 'total_pages' + + get :index, params: {include: 'book-comments'} + JSONAPI.configuration.top_level_meta_include_page_count = false + JSONAPI.configuration.top_level_meta_page_count_key = :page_count + + assert_response :success + assert_equal 91, json_response['meta']['total-pages'] + assert_equal 10, json_response['data'].size + assert_equal 'Book 0', json_response['data'][0]['attributes']['title'] + end + def test_books_offset_pagination_no_params_includes_query_count_one_level Api::V2::BookResource.paginator :offset From 9c80438738c6baf454f2e6471493fe23aa6ceeac Mon Sep 17 00:00:00 2001 From: Brent Jubinville Date: Tue, 3 May 2016 20:52:49 -0400 Subject: [PATCH 7/7] doc(readme): update to highlight page_count options --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 792e47e4e..cb20f43c0 100644 --- a/README.md +++ b/README.md @@ -1877,6 +1877,10 @@ JSONAPI.configure do |config| config.top_level_meta_include_record_count = false config.top_level_meta_record_count_key = :record_count + # For :paged paginators, the following are also available + config.top_level_meta_include_page_count = false + config.top_level_meta_page_count_key = :page_count + config.use_text_errors = false # List of classes that should not be rescued by the operations processor.