diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index 927160f3..0850f741 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -25,11 +25,6 @@ module ActionController "Please pass 'adapter: false' or see ActiveSupport::SerializableResource#serialize" options[:adapter] = false end - if resource.respond_to?(:current_page) && resource.respond_to?(:total_pages) - options[:pagination] = {} - options[:pagination][:original_url] = original_url - options[:pagination][:query_parameters] = query_parameters - end ActiveModel::SerializableResource.serialize(resource, options) do |serializable_resource| if serializable_resource.serializer? serializable_resource.serialization_scope ||= serialization_scope @@ -52,6 +47,7 @@ module ActionController [:_render_option_json, :_render_with_renderer_json].each do |renderer_method| define_method renderer_method do |resource, options| + options.fetch(:context) { options[:context] = request } serializable_resource = get_serializer(resource, options) super(serializable_resource, options) end @@ -62,13 +58,5 @@ module ActionController self._serialization_scope = scope end end - - def original_url - request.original_url[/\A[^?]+/] - end - - def query_parameters - request.query_parameters - end end end diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 7a48942d..0b8118d6 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -21,9 +21,9 @@ module ActiveModel end def as_json(options = nil) - serializable_hash(options).tap do |hash| - include_meta(hash) - end + hash = serializable_hash(options) + include_meta(hash) + hash end def self.create(resource, options = {}) diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index b48e1d20..1b55a812 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -164,11 +164,18 @@ module ActiveModel def add_links(options) links = @hash.fetch(:links) { {} } resources = serializer.instance_variable_get(:@resource) - @hash[:links] = add_pagination_links(links, resources, options) if options[:pagination] + @hash[:links] = add_pagination_links(links, resources, options) if is_paginated?(resources) end def add_pagination_links(links, resources, options) - links.update(JsonApi::PaginationLinks.new(resources).serializable_hash(options)) + pagination_links = JsonApi::PaginationLinks.new(resources, options[:context]).serializable_hash(options) + links.update(pagination_links) + end + + def is_paginated?(resource) + resource.respond_to?(:current_page) && + resource.respond_to?(:total_pages) && + resource.respond_to?(:size) end end end 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 7b608e61..faa053e7 100644 --- a/lib/active_model/serializer/adapter/json_api/pagination_links.rb +++ b/lib/active_model/serializer/adapter/json_api/pagination_links.rb @@ -5,16 +5,15 @@ module ActiveModel class PaginationLinks FIRST_PAGE = 1 - attr_reader :collection + attr_reader :collection, :context - def initialize(collection) - raise_unless_any_gem_installed + def initialize(collection, context) @collection = collection + @context = context end def serializable_hash(options = {}) pages_from.each_with_object({}) do |(key, value), hash| - query_parameters = options[:pagination].fetch(:query_parameters) { {} } params = query_parameters.merge(page: { number: value, size: collection.size }).to_query hash[key] = "#{url(options)}?#{params}" @@ -41,17 +40,17 @@ module ActiveModel end end - def raise_unless_any_gem_installed - return if defined?(WillPaginate) || defined?(Kaminari) - raise <<-EOF - AMS relies on either Kaminari or WillPaginate for pagination. - Please install either dependency by adding one of those to your Gemfile. - EOF - end - def url(options) self_link = options.fetch(:links) {{}} - self_link.fetch(:self) {} ? options[:links][:self] : options[:pagination][:original_url] + self_link.fetch(:self) {} ? options[:links][:self] : original_url + end + + def original_url + @original_url ||= context.original_url[/\A[^?]+/] + end + + def query_parameters + @query_parameters ||= context.query_parameters end end end diff --git a/test/adapter/json_api/pagination_links_test.rb b/test/adapter/json_api/pagination_links_test.rb index 2a624ab7..2fa7a1ab 100644 --- a/test/adapter/json_api/pagination_links_test.rb +++ b/test/adapter/json_api/pagination_links_test.rb @@ -9,6 +9,8 @@ module ActiveModel class Adapter class JsonApi class PaginationLinksTest < Minitest::Test + URI = 'http://example.com' + def setup ActionController::Base.cache_store.clear @array = [ @@ -18,6 +20,14 @@ module ActiveModel ] end + def mock_request(query_parameters={}, original_url=URI) + context = Minitest::Mock.new + context.expect(:original_url, original_url ) + context.expect(:query_parameters, query_parameters) + @options = {} + @options[:context] = context + end + def using_kaminari Kaminari.paginate_array(@array).page(2).per(1) end @@ -38,11 +48,11 @@ module ActiveModel def links { links:{ - self: "http://example.com?page%5Bnumber%5D=2&page%5Bsize%5D=1", - first: "http://example.com?page%5Bnumber%5D=1&page%5Bsize%5D=1", - prev: "http://example.com?page%5Bnumber%5D=1&page%5Bsize%5D=1", - next: "http://example.com?page%5Bnumber%5D=3&page%5Bsize%5D=1", - last: "http://example.com?page%5Bnumber%5D=3&page%5Bsize%5D=1" + self: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1", + first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1", + prev: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1", + next: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1", + last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" } } end @@ -59,7 +69,7 @@ module ActiveModel end def expected_response_with_pagination_links_and_additional_params - new_links = links[:links].each_with_object({}) {|(key, value), hash| hash[key] = "#{value}&teste=teste" } + new_links = links[:links].each_with_object({}) {|(key, value), hash| hash[key] = "#{value}&test=test" } {}.tap do |hash| hash[:data] = [data.values.flatten.second] hash.merge! links: new_links @@ -70,25 +80,25 @@ module ActiveModel serializer = ArraySerializer.new(using_kaminari) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - assert_equal expected_response_with_pagination_links, - adapter.serializable_hash(pagination: { original_url: "http://example.com" }) + mock_request + assert_equal expected_response_with_pagination_links, adapter.serializable_hash(@options) end def test_pagination_links_using_will_paginate serializer = ArraySerializer.new(using_will_paginate) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - assert_equal expected_response_with_pagination_links, - adapter.serializable_hash(pagination: { original_url: "http://example.com" }) + mock_request + assert_equal expected_response_with_pagination_links, adapter.serializable_hash(@options) end def test_pagination_links_with_additional_params serializer = ArraySerializer.new(using_will_paginate) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - assert_equal expected_response_with_pagination_links_and_additional_params, - adapter.serializable_hash(pagination: { original_url: "http://example.com", - query_parameters: { teste: "teste"}}) + mock_request({ test: 'test' }) + assert_equal expected_response_with_pagination_links_and_additional_params, + adapter.serializable_hash(@options) end def test_not_showing_pagination_links