From e62a7d6f34e83d2334c9871ac2648eb440647d6e Mon Sep 17 00:00:00 2001 From: Bruno Bacarini Date: Mon, 10 Aug 2015 11:04:48 -0300 Subject: [PATCH] return complete URIs on pagination links --- docs/howto/add_pagination_links.md | 8 ++++---- lib/action_controller/serialization.rb | 5 +++++ lib/active_model/serializer/adapter/json_api.rb | 4 ++-- .../adapter/json_api/pagination_links.rb | 16 +++++++++++++--- lib/active_model/serializer/array_serializer.rb | 4 ++-- .../json_api/pagination_test.rb | 16 ++++++++++++---- test/action_controller/serialization_test.rb | 6 ++++++ test/adapter/json_api/pagination_links_test.rb | 12 ++++++------ test/array_serializer_test.rb | 2 +- 9 files changed, 51 insertions(+), 22 deletions(-) diff --git a/docs/howto/add_pagination_links.md b/docs/howto/add_pagination_links.md index 0445903d..960723c4 100644 --- a/docs/howto/add_pagination_links.md +++ b/docs/howto/add_pagination_links.md @@ -30,10 +30,10 @@ ex: } ], "links": { - "first": "?page=1&per_page=1", - "prev": "?page=2&per_page=1", - "next": "?page=4&per_page=1", - "last": "?page=13&per_page=1" + "first": "http://example.com/articles?page=1&per_page=1", + "prev": "http://example.com/articles?page=2&per_page=1", + "next": "http://example.com/articles?page=4&per_page=1", + "last": "http://example.com/articles?page=13&per_page=1" } } ``` diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index b216f068..b3b84322 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -25,6 +25,7 @@ module ActionController "Please pass 'adapter: false' or see ActiveSupport::SerializableResource#serialize" options[:adapter] = false end + options[:original_url] = original_url ActiveModel::SerializableResource.serialize(resource, options) do |serializable_resource| if serializable_resource.serializer? serializable_resource.serialization_scope ||= serialization_scope @@ -57,5 +58,9 @@ module ActionController self._serialization_scope = scope end end + + def original_url + request.original_url.sub(/\?.*$/, "") + end end end diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 54de24f0..e30c9bf0 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -29,7 +29,7 @@ module ActiveModel end end - include_pagination_links if serializer.pagination + include_pagination_links if serializer.options[:pagination] else @hash[:data] = attributes_for_serializer(serializer, options) add_resource_relationships(@hash[:data], serializer) @@ -168,7 +168,7 @@ module ActiveModel end def page_links - @links ||= JsonApi::PaginationLinks.new(serializer.resource).page_links + @links ||= JsonApi::PaginationLinks.new(serializer.resource, serializer.options).page_links end def links? diff --git a/lib/active_model/serializer/adapter/json_api/pagination_links.rb b/lib/active_model/serializer/adapter/json_api/pagination_links.rb index 3ebc1c51..dd4c90c1 100644 --- a/lib/active_model/serializer/adapter/json_api/pagination_links.rb +++ b/lib/active_model/serializer/adapter/json_api/pagination_links.rb @@ -5,11 +5,12 @@ module ActiveModel class PaginationLinks FIRST_PAGE = 1 - attr_reader :collection + attr_reader :collection, :options - def initialize(collection) + def initialize(collection, options={}) raise_unless_any_gem_installed @collection = collection + @options = options end def page_links @@ -20,7 +21,7 @@ module ActiveModel def build_links pages_from.each_with_object({}) do |(key, value), hash| - hash[key] = "?page=#{value}&per_page=#{collection.size}" + hash[key] = "#{url}?page=#{value}&per_page=#{collection.size}" end end @@ -45,6 +46,15 @@ module ActiveModel raise "AMS relies on either Kaminari or WillPaginate." + "Please install either dependency by adding one of those to your Gemfile" end + + def url + return default_url unless options && options[:links] && options[:links][:self] + options[:links][:self] + end + + def default_url + options[:original_url] + end end end end diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index 8417d9e2..b97dcd8c 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -5,7 +5,7 @@ module ActiveModel include Enumerable delegate :each, to: :@objects - attr_reader :root, :meta, :meta_key, :pagination, :resource + attr_reader :root, :meta, :meta_key, :options, :resource def initialize(objects, options = {}) @root = options[:root] @@ -24,7 +24,7 @@ module ActiveModel end @meta = options[:meta] @meta_key = options[:meta_key] - @pagination = options[:pagination] + @options = options end def json_key diff --git a/test/action_controller/json_api/pagination_test.rb b/test/action_controller/json_api/pagination_test.rb index 1db50fe9..c8a3647d 100644 --- a/test/action_controller/json_api/pagination_test.rb +++ b/test/action_controller/json_api/pagination_test.rb @@ -47,7 +47,10 @@ module ActionController tests PaginationTestController def test_render_pagination_links_with_will_paginate - expected_links = {"first"=>"?page=1&per_page=1", "prev"=>"?page=1&per_page=1", "next"=>"?page=3&per_page=1", "last"=>"?page=3&per_page=1"} + expected_links = {"first"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=1&per_page=1", + "prev"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=1&per_page=1", + "next"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=3&per_page=1", + "last"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=3&per_page=1"} get :render_pagination_using_will_paginate, page: 2, per_page: 1 response = JSON.parse(@response.body) @@ -55,21 +58,26 @@ module ActionController end def test_render_only_last_and_next_pagination_links - expected_links = {"next"=>"?page=2&per_page=2", "last"=>"?page=2&per_page=2"} + expected_links = {"next"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=2&per_page=2", + "last"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate?page=2&per_page=2"} get :render_pagination_using_will_paginate, page: 1, per_page: 2 response = JSON.parse(@response.body) assert_equal expected_links, response['links'] end def test_render_pagination_links_with_kaminari - expected_links = {"first"=>"?page=1&per_page=1", "prev"=>"?page=1&per_page=1", "next"=>"?page=3&per_page=1", "last"=>"?page=3&per_page=1"} + expected_links = {"first"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=1&per_page=1", + "prev"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=1&per_page=1", + "next"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=3&per_page=1", + "last"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=3&per_page=1"} get :render_pagination_using_kaminari, page: 2, per_page: 1 response = JSON.parse(@response.body) assert_equal expected_links, response['links'] end def test_render_only_prev_and_first_pagination_links - expected_links = {"first"=>"?page=1&per_page=1", "prev"=>"?page=2&per_page=1"} + expected_links = {"first"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=1&per_page=1", + "prev"=>"http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari?page=2&per_page=1"} get :render_pagination_using_kaminari, page: 3, per_page: 1 response = JSON.parse(@response.body) assert_equal expected_links, response['links'] diff --git a/test/action_controller/serialization_test.rb b/test/action_controller/serialization_test.rb index 8c89ceac..d60cdf55 100644 --- a/test/action_controller/serialization_test.rb +++ b/test/action_controller/serialization_test.rb @@ -404,6 +404,9 @@ module ActionController def use_adapter? false end + def original_url + "http://example.com/" + end }.new assert_match /adapter: false/, (capture(:stderr) { controller.get_serializer(Profile.new) @@ -415,6 +418,9 @@ module ActionController def use_adapter? true end + def original_url + "http://example.com/" + end }.new assert_equal "", (capture(:stderr) { controller.get_serializer(Profile.new) diff --git a/test/adapter/json_api/pagination_links_test.rb b/test/adapter/json_api/pagination_links_test.rb index 94f4632d..7c26c192 100644 --- a/test/adapter/json_api/pagination_links_test.rb +++ b/test/adapter/json_api/pagination_links_test.rb @@ -50,23 +50,23 @@ module ActiveModel } }], links:{ - first:"?page=1&per_page=1", - prev:"?page=1&per_page=1", - next:"?page=3&per_page=1", - last:"?page=3&per_page=1" + first: "http://example.com?page=1&per_page=1", + prev: "http://example.com?page=1&per_page=1", + next: "http://example.com?page=3&per_page=1", + last: "http://example.com?page=3&per_page=1" } } end def test_pagination_links_using_kaminari - serializer = ArraySerializer.new(using_kaminari, pagination: true) + serializer = ArraySerializer.new(using_kaminari, pagination: true, original_url: "http://example.com") adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) assert_equal expected_response_with_pagination_links, adapter.serializable_hash end def test_pagination_links_using_will_paginate - serializer = ArraySerializer.new(using_will_paginate, pagination: true) + serializer = ArraySerializer.new(using_will_paginate, pagination: true, original_url: "http://example.com") adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) assert_equal expected_response_with_pagination_links, adapter.serializable_hash diff --git a/test/array_serializer_test.rb b/test/array_serializer_test.rb index 60caf9bc..b5eb9384 100644 --- a/test/array_serializer_test.rb +++ b/test/array_serializer_test.rb @@ -95,7 +95,7 @@ module ActiveModel def test_pagination_attr_readers serializer = ArraySerializer.new(@resource, pagination: true) - assert_equal serializer.pagination, true + assert_equal serializer.options[:pagination], true end def test_resource