From d6d6cb5b077073b95df0412a9c1879f3e9912fc7 Mon Sep 17 00:00:00 2001 From: Arne Zeising Date: Wed, 20 Jun 2018 12:08:05 +0200 Subject: [PATCH 1/2] Allow pagination for nested resources but not for included resources --- lib/jsonapi/active_relation_resource_finder.rb | 9 +++++---- lib/jsonapi/processor.rb | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/jsonapi/active_relation_resource_finder.rb b/lib/jsonapi/active_relation_resource_finder.rb index af6595a01..2701ad88c 100644 --- a/lib/jsonapi/active_relation_resource_finder.rb +++ b/lib/jsonapi/active_relation_resource_finder.rb @@ -110,13 +110,13 @@ def find_fragments(filters, options = {}) # @return [Hash{ResourceIdentity => {identity: => ResourceIdentity, cache: cache_field, attributes: => {name => value}, related: {relationship_name: [] }}}] # the ResourceInstances matching the filters, sorting, and pagination rules along with any request # additional_field values - def find_related_fragments(source_rids, relationship_name, options = {}) + def find_related_fragments(source_rids, relationship_name, options = {}, included_key = nil) relationship = _relationship(relationship_name) if relationship.polymorphic? && relationship.foreign_key_on == :self find_related_polymorphic_fragments(source_rids, relationship, options) else - find_related_monomorphic_fragments(source_rids, relationship, options) + find_related_monomorphic_fragments(source_rids, relationship, included_key, options) end end @@ -162,7 +162,7 @@ def find_records_by_keys(keys, options = {}) records.where({ _primary_key => keys }) end - def find_related_monomorphic_fragments(source_rids, relationship, options = {}) + def find_related_monomorphic_fragments(source_rids, relationship, included_key, options = {}) source_ids = source_rids.collect {|rid| rid.id} context = options[:context] @@ -185,7 +185,8 @@ def find_related_monomorphic_fragments(source_rids, relationship, options = {}) # ToDO: Remove count check. Currently pagination isn't working with multiple source_rids (i.e. it only works # for show relationships, not related includes). - if paginator && source_rids.count == 1 + # Check included_key to not paginate included resources but ensure that nested resources can be paginated + if paginator && source_rids.count == 1 && !included_key records = related_klass.apply_pagination(records, paginator, order_options) end diff --git a/lib/jsonapi/processor.rb b/lib/jsonapi/processor.rb index 13c5cbde7..68a1e0d5c 100644 --- a/lib/jsonapi/processor.rb +++ b/lib/jsonapi/processor.rb @@ -469,7 +469,9 @@ def get_related(resource_klass, source_resources, include_related, options) find_related_resource_options[:sort_criteria] = relationship.resource_klass.default_sort find_related_resource_options[:cache] = resource_klass.caching? - related_identities = resource_klass.find_related_fragments(source_rids, relationship_name, find_related_resource_options) + related_identities = resource_klass.find_related_fragments( + source_rids, relationship_name, find_related_resource_options, key + ) related_identities.each_pair do |identity, v| related[relationship_name][:resources][identity] = From abe63e57e2dedaef1b20e100f3551814dd0843b9 Mon Sep 17 00:00:00 2001 From: Arne Zeising Date: Wed, 20 Jun 2018 14:45:44 +0200 Subject: [PATCH 2/2] Add tests for included key Fixes #1162 --- .../active_relation_resource_finder_test.rb | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/test/unit/resource/active_relation_resource_finder_test.rb b/test/unit/resource/active_relation_resource_finder_test.rb index 228103689..a329a9eba 100644 --- a/test/unit/resource/active_relation_resource_finder_test.rb +++ b/test/unit/resource/active_relation_resource_finder_test.rb @@ -121,6 +121,36 @@ def test_find_related_has_many_fragments_no_attributes assert_equal 2, related_identities[JSONAPI::ResourceIdentity.new(TagResource, 502)][:related][:tags].length end + def test_find_related_has_many_fragments_pagination + params = ActionController::Parameters.new(number: 2, size: 4) + options = { paginator: PagedPaginator.new(params) } + source_rids = [JSONAPI::ResourceIdentity.new(ARPostResource, 15)] + + related_identities = ARPostResource.find_related_fragments(source_rids, 'tags', options) + + assert_equal 1, related_identities.length + assert_equal JSONAPI::ResourceIdentity.new(TagResource, 516), related_identities.keys[0] + assert_equal JSONAPI::ResourceIdentity.new(TagResource, 516), related_identities.values[0][:identity] + assert related_identities.values[0].is_a?(Hash) + assert_equal 2, related_identities.values[0].length + assert_equal 1, related_identities.values[0][:related][:tags].length + end + + def test_find_related_has_many_fragments_pagination_included_key + params = ActionController::Parameters.new(number: 2, size: 4) + options = { paginator: PagedPaginator.new(params) } + source_rids = [JSONAPI::ResourceIdentity.new(ARPostResource, 15)] + + related_identities = ARPostResource.find_related_fragments(source_rids, 'tags', options, :tags) + + assert_equal 5, related_identities.length + assert_equal JSONAPI::ResourceIdentity.new(TagResource, 502), related_identities.keys[0] + assert_equal JSONAPI::ResourceIdentity.new(TagResource, 502), related_identities.values[0][:identity] + assert related_identities.values[0].is_a?(Hash) + assert_equal 2, related_identities.values[0].length + assert_equal 1, related_identities.values[0][:related][:tags].length + end + def test_find_related_has_many_fragments_cache_field options = { cache: true } source_rids = [JSONAPI::ResourceIdentity.new(ARPostResource, 1), @@ -200,7 +230,7 @@ def test_find_related_polymorphic_fragments_cache_field end def test_find_related_polymorphic_fragments_cache_field_attributes - options = { cache: true , attributes: [:name] } + options = { cache: true, attributes: [:name] } source_rids = [JSONAPI::ResourceIdentity.new(PictureResource, 1), JSONAPI::ResourceIdentity.new(PictureResource, 2), JSONAPI::ResourceIdentity.new(PictureResource, 20)]