Skip to content

Commit 3f55ee6

Browse files
committed
Introduce ResourceSet, ResourceIdTree, and ResourceFragment helper classes
1 parent 4c3c771 commit 3f55ee6

18 files changed

+1141
-562
lines changed

lib/jsonapi-resources.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@
2727
require 'jsonapi/active_relation_resource_finder'
2828
require 'jsonapi/active_relation_resource_finder/join_tree'
2929
require 'jsonapi/resource_identity'
30+
require 'jsonapi/resource_fragment'
31+
require 'jsonapi/resource_id_tree'
32+
require 'jsonapi/resource_set'

lib/jsonapi/active_relation_resource_finder.rb

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,17 @@ def find_fragments(filters, options = {})
8282
fragments = {}
8383
records.pluck(*pluck_fields).collect do |row|
8484
rid = JSONAPI::ResourceIdentity.new(self, pluck_fields.length == 1 ? row : row[0])
85-
fragments[rid] = { identity: rid }
85+
86+
fragments[rid] ||= JSONAPI::ResourceFragment.new(rid)
8687
attributes_offset = 1
8788

8889
if cache_field
89-
fragments[rid][:cache] = cast_to_attribute_type(row[1], cache_field[:type])
90+
fragments[rid].cache = cast_to_attribute_type(row[1], cache_field[:type])
9091
attributes_offset+= 1
9192
end
9293

93-
fragments[rid][:attributes]= {} unless model_fields.empty?
9494
model_fields.each_with_index do |k, idx|
95-
fragments[rid][:attributes][k[0]]= cast_to_attribute_type(row[idx + attributes_offset], k[1][:type])
95+
fragments[rid].attributes[k[0]]= cast_to_attribute_type(row[idx + attributes_offset], k[1][:type])
9696
end
9797
end
9898

@@ -110,13 +110,23 @@ def find_fragments(filters, options = {})
110110
# @return [Hash{ResourceIdentity => {identity: => ResourceIdentity, cache: cache_field, attributes: => {name => value}, related: {relationship_name: [] }}}]
111111
# the ResourceInstances matching the filters, sorting, and pagination rules along with any request
112112
# additional_field values
113-
def find_related_fragments(source_rids, relationship_name, options = {}, included_key = nil)
113+
def find_related_fragments(source_rids, relationship_name, options = {})
114+
relationship = _relationship(relationship_name)
115+
116+
if relationship.polymorphic? && relationship.foreign_key_on == :self
117+
find_related_polymorphic_fragments(source_rids, relationship, options, false)
118+
else
119+
find_related_monomorphic_fragments(source_rids, relationship, options, false)
120+
end
121+
end
122+
123+
def find_included_fragments(source_rids, relationship_name, options = {})
114124
relationship = _relationship(relationship_name)
115125

116126
if relationship.polymorphic? && relationship.foreign_key_on == :self
117-
find_related_polymorphic_fragments(source_rids, relationship, options)
127+
find_related_polymorphic_fragments(source_rids, relationship, options, true)
118128
else
119-
find_related_monomorphic_fragments(source_rids, relationship, included_key, options)
129+
find_related_monomorphic_fragments(source_rids, relationship, options, true)
120130
end
121131
end
122132

@@ -215,7 +225,7 @@ def find_records_by_keys(keys, options = {})
215225
records(options).where({ _primary_key => keys })
216226
end
217227

218-
def find_related_monomorphic_fragments(source_rids, relationship, included_key, options = {})
228+
def find_related_monomorphic_fragments(source_rids, relationship, options, connect_source_identity)
219229
opts = options.dup
220230

221231
source_ids = source_rids.collect {|rid| rid.id}
@@ -260,8 +270,7 @@ def find_related_monomorphic_fragments(source_rids, relationship, included_key,
260270

261271
# ToDO: Remove count check. Currently pagination isn't working with multiple source_rids (i.e. it only works
262272
# for show relationships, not related includes).
263-
# Check included_key to not paginate included resources but ensure that nested resources can be paginated
264-
if paginator && source_rids.count == 1 && !included_key
273+
if paginator && source_rids.count == 1
265274
records = related_klass.apply_pagination(records, paginator, order_options)
266275
end
267276

@@ -287,28 +296,35 @@ def find_related_monomorphic_fragments(source_rids, relationship, included_key,
287296

288297
rows = records.pluck(*pluck_fields)
289298

290-
relation_name = relationship.name.to_sym
291-
292299
related_fragments = {}
293300

294301
rows.each do |row|
295302
unless row[1].nil?
296303
rid = JSONAPI::ResourceIdentity.new(related_klass, row[1])
297-
related_fragments[rid] ||= { identity: rid, related: {relation_name => [] } }
304+
305+
related_fragments[rid] ||= JSONAPI::ResourceFragment.new(rid)
298306

299307
attributes_offset = 2
300308

301309
if cache_field
302-
related_fragments[rid][:cache] = cast_to_attribute_type(row[attributes_offset], cache_field[:type])
310+
related_fragments[rid].cache = cast_to_attribute_type(row[attributes_offset], cache_field[:type])
303311
attributes_offset+= 1
304312
end
305313

306-
related_fragments[rid][:attributes]= {} unless model_fields.empty?
307314
model_fields.each_with_index do |k, idx|
308-
related_fragments[rid][:attributes][k[0]] = cast_to_attribute_type(row[idx + attributes_offset], k[1][:type])
315+
related_fragments[rid].attributes[k[0]] = cast_to_attribute_type(row[idx + attributes_offset], k[1][:type])
309316
end
310317

311-
related_fragments[rid][:related][relation_name] << JSONAPI::ResourceIdentity.new(self, row[0])
318+
source_rid = JSONAPI::ResourceIdentity.new(self, row[0])
319+
320+
related_fragments[rid].add_related_from(source_rid)
321+
322+
if connect_source_identity
323+
related_relationship = related_klass._relationships[relationship.inverse_relationship]
324+
if related_relationship
325+
related_fragments[rid].add_related_identity(related_relationship.name, source_rid)
326+
end
327+
end
312328
end
313329
end
314330

@@ -317,7 +333,7 @@ def find_related_monomorphic_fragments(source_rids, relationship, included_key,
317333

318334
# Gets resource identities where the related resource is polymorphic and the resource type and id
319335
# are stored on the primary resources. Cache fields will always be on the related resources.
320-
def find_related_polymorphic_fragments(source_rids, relationship, options = {})
336+
def find_related_polymorphic_fragments(source_rids, relationship, options, connect_source_identity)
321337
source_ids = source_rids.collect {|rid| rid.id}
322338

323339
context = options[:context]
@@ -393,17 +409,24 @@ def find_related_polymorphic_fragments(source_rids, relationship, options = {})
393409

394410
rows = records.pluck(*pluck_fields)
395411

396-
relation_name = relationship.name.to_sym
397-
398412
related_fragments = {}
399413

400414
rows.each do |row|
401415
unless row[1].nil? || row[2].nil?
402416
related_klass = resource_klass_for(row[2])
403417

404418
rid = JSONAPI::ResourceIdentity.new(related_klass, row[1])
405-
related_fragments[rid] ||= { identity: rid, related: { relation_name => [] } }
406-
related_fragments[rid][:related][relation_name] << JSONAPI::ResourceIdentity.new(self, row[0])
419+
related_fragments[rid] ||= JSONAPI::ResourceFragment.new(rid)
420+
421+
source_rid = JSONAPI::ResourceIdentity.new(self, row[0])
422+
related_fragments[rid].add_related_from(source_rid)
423+
424+
if connect_source_identity
425+
related_relationship = related_klass._relationships[relationship.inverse_relationship]
426+
if related_relationship
427+
related_fragments[rid].add_related_identity(related_relationship.name, source_rid)
428+
end
429+
end
407430

408431
relation_position = relation_positions[row[2]]
409432
model_fields = relation_position[:model_fields]
@@ -413,14 +436,13 @@ def find_related_polymorphic_fragments(source_rids, relationship, options = {})
413436
attributes_offset = 0
414437

415438
if cache_field
416-
related_fragments[rid][:cache] = cast_to_attribute_type(row[field_offset], cache_field[:type])
439+
related_fragments[rid].cache = cast_to_attribute_type(row[field_offset], cache_field[:type])
417440
attributes_offset+= 1
418441
end
419442

420443
if attributes.length > 0
421-
related_fragments[rid][:attributes]= {}
422444
model_fields.each_with_index do |k, idx|
423-
related_fragments[rid][:attributes][k[0]] = cast_to_attribute_type(row[idx + field_offset + attributes_offset], k[1][:type])
445+
related_fragments[rid].add_attribute(k[0], cast_to_attribute_type(row[idx + field_offset + attributes_offset], k[1][:type]))
424446
end
425447
end
426448
end
@@ -615,4 +637,4 @@ def apply_filter(records, filter, value, options = {})
615637
end
616638
end
617639
end
618-
end
640+
end

lib/jsonapi/exceptions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module JSONAPI
22
module Exceptions
33
class Error < RuntimeError
4-
attr :error_object_overrides
4+
attr_reader :error_object_overrides
55

66
def initialize(error_object_overrides = {})
77
@error_object_overrides = error_object_overrides

lib/jsonapi/operation_result.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def initialize(code, resource_set, options = {})
4949

5050
def to_hash(serializer)
5151
if serializer
52-
serializer.serialize_resource_set_to_hash(resource_set)
52+
serializer.serialize_resource_set_to_hash_single(resource_set)
5353
else
5454
# :nocov:
5555
{}
@@ -71,7 +71,7 @@ def initialize(code, resource_set, options = {})
7171

7272
def to_hash(serializer)
7373
if serializer
74-
serializer.serialize_resources_set_to_hash(resource_set)
74+
serializer.serialize_resource_set_to_hash_plural(resource_set)
7575
else
7676
# :nocov:
7777
{}
@@ -91,7 +91,7 @@ def initialize(code, source_resource, type, resource_set, options = {})
9191

9292
def to_hash(serializer = nil)
9393
if serializer
94-
serializer.serialize_related_resources_set_to_hash(source_resource, resource_set)
94+
serializer.serialize_related_resource_set_to_hash_plural(resource_set, source_resource)
9595
else
9696
# :nocov:
9797
{}

0 commit comments

Comments
 (0)