Skip to content

Commit e6c60e6

Browse files
arnaud-moncelDogan AY
andauthored
fix(rpc agent): avoid error on rpc relation computing (#266)
Co-authored-by: Dogan AY <dogan.ay@forestadmin.com>
1 parent a729194 commit e6c60e6

File tree

2 files changed

+196
-2
lines changed
  • packages/forest_admin_rpc_agent

2 files changed

+196
-2
lines changed

packages/forest_admin_rpc_agent/lib/forest_admin_rpc_agent/agent.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ def build_rpc_schema_from_datasource(datasource)
9797
# RPC collection → extract relations to non-RPC collections
9898
collection.schema[:fields].each do |field_name, field|
9999
next if field.type == 'Column'
100-
next if @rpc_collections.include?(field.foreign_collection)
100+
next if relation_targets_rpc_collection?(field)
101101

102102
relations[field_name] = field
103103
end
104104
else
105105
fields = {}
106106

107107
collection.schema[:fields].each do |field_name, field|
108-
if field.type != 'Column' && @rpc_collections.include?(field.foreign_collection)
108+
if field.type != 'Column' && relation_targets_rpc_collection?(field)
109109
relations[field_name] = field
110110
else
111111
if field.type == 'Column'
@@ -134,6 +134,14 @@ def build_rpc_schema_from_datasource(datasource)
134134
schema
135135
end
136136

137+
def relation_targets_rpc_collection?(relation)
138+
if relation.type == 'PolymorphicManyToOne'
139+
relation.foreign_collections.any? { |fc| @rpc_collections.include?(fc) }
140+
else
141+
@rpc_collections.include?(relation.foreign_collection)
142+
end
143+
end
144+
137145
def compute_and_cache_hash
138146
return unless @cached_schema
139147

packages/forest_admin_rpc_agent/spec/lib/forest_admin_rpc_agent/agent_spec.rb

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,192 @@ module ForestAdminRpcAgent
349349
expect(rpc_relations_for_rpc1).not_to have_key('other_rpc')
350350
end
351351

352+
context 'with PolymorphicManyToOne relations' do
353+
it 'extracts polymorphic relation from RPC collection when targeting non-RPC collections' do
354+
rpc_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
355+
normal_collection1 = instance_double(ForestAdminDatasourceToolkit::Collection)
356+
normal_collection2 = instance_double(ForestAdminDatasourceToolkit::Collection)
357+
358+
polymorphic_field = instance_double(
359+
ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
360+
)
361+
allow(polymorphic_field).to receive_messages(
362+
type: 'PolymorphicManyToOne',
363+
foreign_collections: %w[NormalCollection1 NormalCollection2]
364+
)
365+
366+
allow(rpc_collection).to receive_messages(
367+
name: 'RpcCollection',
368+
schema: { fields: { 'commentable' => polymorphic_field } }
369+
)
370+
allow(normal_collection1).to receive_messages(name: 'NormalCollection1', schema: { fields: {} })
371+
allow(normal_collection2).to receive_messages(name: 'NormalCollection2', schema: { fields: {} })
372+
allow(datasource).to receive_messages(
373+
collections: {
374+
'RpcCollection' => rpc_collection,
375+
'NormalCollection1' => normal_collection1,
376+
'NormalCollection2' => normal_collection2
377+
},
378+
live_query_connections: {}
379+
)
380+
381+
instance.mark_collections_as_rpc('RpcCollection')
382+
instance.send_schema
383+
384+
expect(instance.cached_schema[:rpc_relations]).to have_key('RpcCollection')
385+
expect(instance.cached_schema[:rpc_relations]['RpcCollection']).to have_key('commentable')
386+
end
387+
388+
it 'does not extract polymorphic relation from RPC collection when all targets are RPC' do
389+
rpc_collection1 = instance_double(ForestAdminDatasourceToolkit::Collection)
390+
rpc_collection2 = instance_double(ForestAdminDatasourceToolkit::Collection)
391+
rpc_collection3 = instance_double(ForestAdminDatasourceToolkit::Collection)
392+
393+
polymorphic_field = instance_double(
394+
ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
395+
)
396+
allow(polymorphic_field).to receive_messages(
397+
type: 'PolymorphicManyToOne',
398+
foreign_collections: %w[RpcCollection2 RpcCollection3]
399+
)
400+
401+
allow(rpc_collection1).to receive_messages(
402+
name: 'RpcCollection1',
403+
schema: { fields: { 'commentable' => polymorphic_field } }
404+
)
405+
allow(rpc_collection2).to receive_messages(name: 'RpcCollection2', schema: { fields: {} })
406+
allow(rpc_collection3).to receive_messages(name: 'RpcCollection3', schema: { fields: {} })
407+
allow(datasource).to receive_messages(
408+
collections: {
409+
'RpcCollection1' => rpc_collection1,
410+
'RpcCollection2' => rpc_collection2,
411+
'RpcCollection3' => rpc_collection3
412+
},
413+
live_query_connections: {}
414+
)
415+
416+
instance.mark_collections_as_rpc('RpcCollection1', 'RpcCollection2', 'RpcCollection3')
417+
instance.send_schema
418+
419+
rpc_relations_for_rpc1 = instance.cached_schema[:rpc_relations]['RpcCollection1'] || {}
420+
expect(rpc_relations_for_rpc1).not_to have_key('commentable')
421+
end
422+
423+
it 'extracts polymorphic relation from RPC collection when some targets are RPC and some are not' do
424+
rpc_collection1 = instance_double(ForestAdminDatasourceToolkit::Collection)
425+
rpc_collection2 = instance_double(ForestAdminDatasourceToolkit::Collection)
426+
normal_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
427+
428+
polymorphic_field = instance_double(
429+
ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
430+
)
431+
allow(polymorphic_field).to receive_messages(
432+
type: 'PolymorphicManyToOne',
433+
foreign_collections: %w[RpcCollection2 NormalCollection]
434+
)
435+
436+
allow(rpc_collection1).to receive_messages(
437+
name: 'RpcCollection1',
438+
schema: { fields: { 'commentable' => polymorphic_field } }
439+
)
440+
allow(rpc_collection2).to receive_messages(name: 'RpcCollection2', schema: { fields: {} })
441+
allow(normal_collection).to receive_messages(name: 'NormalCollection', schema: { fields: {} })
442+
allow(datasource).to receive_messages(
443+
collections: {
444+
'RpcCollection1' => rpc_collection1,
445+
'RpcCollection2' => rpc_collection2,
446+
'NormalCollection' => normal_collection
447+
},
448+
live_query_connections: {}
449+
)
450+
451+
instance.mark_collections_as_rpc('RpcCollection1', 'RpcCollection2')
452+
instance.send_schema
453+
454+
# Mixed targets: at least one is RPC, so the relation is NOT extracted for RPC collections
455+
# (the `next if relation_targets_rpc_collection?` skips it because .any? returns true)
456+
rpc_relations_for_rpc1 = instance.cached_schema[:rpc_relations]['RpcCollection1'] || {}
457+
expect(rpc_relations_for_rpc1).not_to have_key('commentable')
458+
end
459+
460+
it 'extracts polymorphic relation from normal collection when any target is an RPC collection' do
461+
rpc_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
462+
normal_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
463+
normal_collection2 = instance_double(ForestAdminDatasourceToolkit::Collection)
464+
465+
polymorphic_field = instance_double(
466+
ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
467+
)
468+
allow(polymorphic_field).to receive_messages(
469+
type: 'PolymorphicManyToOne',
470+
foreign_collections: %w[RpcCollection NormalCollection2]
471+
)
472+
473+
allow(rpc_collection).to receive_messages(name: 'RpcCollection', schema: { fields: {} })
474+
allow(normal_collection).to receive_messages(
475+
name: 'NormalCollection',
476+
schema: { fields: { 'commentable' => polymorphic_field } }
477+
)
478+
allow(normal_collection2).to receive_messages(name: 'NormalCollection2', schema: { fields: {} })
479+
allow(datasource).to receive_messages(
480+
collections: {
481+
'RpcCollection' => rpc_collection,
482+
'NormalCollection' => normal_collection,
483+
'NormalCollection2' => normal_collection2
484+
},
485+
live_query_connections: {}
486+
)
487+
488+
instance.mark_collections_as_rpc('RpcCollection')
489+
instance.send_schema
490+
491+
expect(instance.cached_schema[:rpc_relations]).to have_key('NormalCollection')
492+
expect(instance.cached_schema[:rpc_relations]['NormalCollection']).to have_key('commentable')
493+
end
494+
495+
it 'does not extract polymorphic relation from normal collection when no target is RPC' do
496+
normal_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
497+
normal_collection2 = instance_double(ForestAdminDatasourceToolkit::Collection)
498+
normal_collection3 = instance_double(ForestAdminDatasourceToolkit::Collection)
499+
500+
polymorphic_field = instance_double(
501+
ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
502+
)
503+
allow(polymorphic_field).to receive_messages(
504+
type: 'PolymorphicManyToOne',
505+
foreign_collections: %w[NormalCollection2 NormalCollection3]
506+
)
507+
508+
column_field = instance_double(ForestAdminDatasourceToolkit::Schema::ColumnSchema)
509+
allow(column_field).to receive_messages(type: 'Column')
510+
allow(column_field).to receive(:filter_operators=)
511+
allow(column_field).to receive(:filter_operators).and_return([])
512+
allow(ForestAdminAgent::Utils::Schema::FrontendFilterable).to receive(:sort_operators).and_return([])
513+
514+
allow(normal_collection).to receive_messages(
515+
name: 'NormalCollection',
516+
schema: { fields: { 'id' => column_field, 'commentable' => polymorphic_field } }
517+
)
518+
allow(normal_collection2).to receive_messages(name: 'NormalCollection2', schema: { fields: {} })
519+
allow(normal_collection3).to receive_messages(name: 'NormalCollection3', schema: { fields: {} })
520+
allow(datasource).to receive_messages(
521+
collections: {
522+
'NormalCollection' => normal_collection,
523+
'NormalCollection2' => normal_collection2,
524+
'NormalCollection3' => normal_collection3
525+
},
526+
live_query_connections: {}
527+
)
528+
529+
instance.send_schema
530+
531+
# No RPC targets, so the polymorphic relation stays in the normal collection's fields
532+
expect(instance.cached_schema[:rpc_relations]).not_to have_key('NormalCollection')
533+
normal_schema = instance.cached_schema[:collections].find { |c| c[:name] == 'NormalCollection' }
534+
expect(normal_schema[:fields]).to have_key('commentable')
535+
end
536+
end
537+
352538
it 'sorts filter_operators for Column fields' do
353539
normal_collection = instance_double(ForestAdminDatasourceToolkit::Collection)
354540
column_field = instance_double(ForestAdminDatasourceToolkit::Schema::ColumnSchema)

0 commit comments

Comments
 (0)