From b30704e30aa5e3599223d9bdc0807b861181d0c6 Mon Sep 17 00:00:00 2001 From: Brandon Caplan Date: Wed, 2 Aug 2017 14:19:06 -0700 Subject: [PATCH] Prevent out of bounds pages from returning a next link. Also makes sure the prev link is a real page. Self link is unmodified, it will return a link to the current page even if it doesn't exist. Seemed to best conform to JSON:API spec. --- CHANGELOG.md | 1 + .../adapter/json_api/pagination_links.rb | 7 ++-- .../adapter/json_api/pagination_links_test.rb | 35 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56059d968..83d900718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Features: Fixes: - [#2022](https://github.com/rails-api/active_model_serializers/pull/2022) Mutation of ActiveModelSerializers::Model now changes the attributes. Originally in [#1984](https://github.com/rails-api/active_model_serializers/pull/1984). (@bf4) +- [#2171](https://github.com/rails-api/active_model_serializers/pull/2171) Prevent the `next` link from getting populated in JSON:API when an out of bounds page is requested. (@bcaplan) - [#2200](https://github.com/rails-api/active_model_serializers/pull/2200) Fix deserialization of polymorphic relationships. (@dennis95stumm) Misc: diff --git a/lib/active_model_serializers/adapter/json_api/pagination_links.rb b/lib/active_model_serializers/adapter/json_api/pagination_links.rb index 859368b0c..992d7df83 100644 --- a/lib/active_model_serializers/adapter/json_api/pagination_links.rb +++ b/lib/active_model_serializers/adapter/json_api/pagination_links.rb @@ -53,11 +53,14 @@ def last_page_url def prev_page_url return nil if collection.current_page == FIRST_PAGE - url_for_page(collection.current_page - FIRST_PAGE) + + page_number = collection.current_page > collection.total_pages ? collection.total_pages : collection.current_page - FIRST_PAGE + + url_for_page(page_number) end def next_page_url - return nil if collection.total_pages == 0 || collection.current_page == collection.total_pages + return nil if collection.total_pages == 0 || collection.current_page >= collection.total_pages url_for_page(collection.next_page) end diff --git a/test/adapter/json_api/pagination_links_test.rb b/test/adapter/json_api/pagination_links_test.rb index 3cdbab0ef..029a4403a 100644 --- a/test/adapter/json_api/pagination_links_test.rb +++ b/test/adapter/json_api/pagination_links_test.rb @@ -88,6 +88,18 @@ def last_page_links } end + def out_of_bounds_page_links + { + links: { + self: "#{URI}?page%5Bnumber%5D=4&page%5Bsize%5D=2", + first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2", + prev: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2", + next: nil, + last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2" + } + } + end + def expected_response_when_unpaginatable data end @@ -120,6 +132,13 @@ def expected_response_with_last_page_pagination_links end end + def expected_response_with_out_of_bounds_page_pagination_links + {}.tap do |hash| + hash[:data] = [] + hash.merge! out_of_bounds_page_links + end + end + def expected_response_with_empty_collection_pagination_links {}.tap do |hash| hash[:data] = [] @@ -174,6 +193,22 @@ def test_last_page_pagination_links_using_will_paginate assert_equal expected_response_with_last_page_pagination_links, adapter.serializable_hash end + def test_out_of_bounds_page_pagination_links_using_kaminari + out_of_bounds_page_number = 4 + + adapter = load_adapter(using_kaminari(out_of_bounds_page_number), mock_request) + + assert_equal expected_response_with_out_of_bounds_page_pagination_links, adapter.serializable_hash + end + + def test_out_of_bounds_page_pagination_links_using_will_paginate + out_of_bounds_page_number = 4 + + adapter = load_adapter(using_will_paginate(out_of_bounds_page_number), mock_request) + + assert_equal expected_response_with_out_of_bounds_page_pagination_links, adapter.serializable_hash + end + def test_not_showing_pagination_links adapter = load_adapter(@array, mock_request)