forest_admin_agent 1.0.0.pre.beta.61 → 1.0.0.pre.beta.62

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ed026aeaff7bcb843203155a82a115b5f1309dfdeb9a4d65471e57097c3d815
4
- data.tar.gz: a70a80b55f3ed8e4334498c0cc2cade66446926cab06a7df317656690bece175
3
+ metadata.gz: 8094394fa87dd1d0c83fac337a16804b9aefa3592bf3398b4ae859a45de031af
4
+ data.tar.gz: 38438b2a1f495a1b448796e742189103a8180bb8322735ae5b88708557da505b
5
5
  SHA512:
6
- metadata.gz: cd8383d29284ae83e1eeb43bfdab09135426afae3e1f554201740c81aa914790565dd723d386f651af19801e54bfa9c2337bbc1b229a538dab69f0e5ddfc15d8
7
- data.tar.gz: cabab68549e79011e15ad76541174c0ce5d88115fc6ed9d501fc074754ce0943ce6839454bbdac4430b2f9a58d3f45f072ff7ceb3228f715f5716c24df036a8c
6
+ metadata.gz: ce0cf6bfd2a8da01400c0f12ee772e2274327613c3dcb4c89806415b1f13602b3c8e5fa397ad7f75dcbc511657ab3ebb7bb1f3e1555ba9dc2dcfb3f1186a2822
7
+ data.tar.gz: 2b1d5f879c66af69ccd73aa160261fd4c293a39cfdee463e536dc7efd8e367f4eca979e7231a517d7895607425b9f0580b2f835a1d3b2001caeb34b8c4eb6351
@@ -19,7 +19,7 @@ module ForestAdminAgent
19
19
  record[schema.foreign_key] = value['data'][schema.foreign_key_target] if schema.type == 'ManyToOne'
20
20
  end
21
21
 
22
- record
22
+ record || {}
23
23
  end
24
24
  end
25
25
  end
@@ -5,7 +5,11 @@ module ForestAdminAgent
5
5
  super
6
6
 
7
7
  relation = @collection.schema[:fields][args[:params]['relation_name']]
8
- @child_collection = @datasource.get_collection(relation.foreign_collection)
8
+ @child_collection = if relation.type == 'PolymorphicManyToOne'
9
+ @datasource.get_collection(args[:params]['data']['type'])
10
+ else
11
+ @datasource.get_collection(relation.foreign_collection)
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -37,6 +37,25 @@ module ForestAdminAgent
37
37
  def delete_records(args, selection_ids)
38
38
  condition_tree_ids = ConditionTree::ConditionTreeFactory.match_records(@collection, selection_ids[:ids])
39
39
  condition_tree_ids = condition_tree_ids.inverse if selection_ids[:are_excluded]
40
+
41
+ @collection.schema[:fields].each_value do |field_schema|
42
+ next unless field_schema.type == 'PolymorphicOneToOne' || field_schema.type == 'PolymorphicOneToMany'
43
+
44
+ condition_tree = Nodes::ConditionTreeBranch.new(
45
+ 'And',
46
+ [
47
+ Nodes::ConditionTreeLeaf.new(field_schema.origin_key, Operators::IN,
48
+ selection_ids[:ids].map { |value| value['id'] }),
49
+ Nodes::ConditionTreeLeaf.new(field_schema.origin_type_field, Operators::EQUAL,
50
+ @collection.name.gsub('__', '::'))
51
+ ]
52
+ )
53
+ filter = Filter.new(condition_tree: condition_tree)
54
+ @datasource.get_collection(field_schema.foreign_collection)
55
+ .update(@caller, filter, { field_schema.origin_key => nil,
56
+ field_schema.origin_type_field => nil })
57
+ end
58
+
40
59
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
41
60
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
42
61
  [
@@ -38,7 +38,7 @@ module ForestAdminAgent
38
38
  class_name: @collection.name,
39
39
  is_collection: true,
40
40
  serializer: Serializer::ForestSerializer,
41
- include: projection.relations.keys,
41
+ include: projection.relations(only_keys: true),
42
42
  meta: handle_search_decorator(args[:params]['search'], records)
43
43
  )
44
44
  }
@@ -28,10 +28,13 @@ module ForestAdminAgent
28
28
  target_relation_id = Utils::Id.unpack_id(@child_collection, args[:params]['data'][0]['id'], with_key: true)
29
29
  relation = Schema.get_to_many_relation(@collection, args[:params]['relation_name'])
30
30
 
31
- if relation.type == 'OneToMany'
31
+ case relation.type
32
+ when 'OneToMany'
32
33
  associate_one_to_many(relation, parent_id, target_relation_id)
33
- else
34
+ when 'ManyToMany'
34
35
  associate_many_to_many(relation, parent_id, target_relation_id)
36
+ when 'PolymorphicOneToMany'
37
+ associate_polymorphic_one_to_many(relation, parent_id, target_relation_id)
35
38
  end
36
39
 
37
40
  { content: nil, status: 204 }
@@ -55,6 +58,27 @@ module ForestAdminAgent
55
58
  @child_collection.update(@caller, filter, { relation.origin_key => value })
56
59
  end
57
60
 
61
+ def associate_polymorphic_one_to_many(relation, parent_id, target_relation_id)
62
+ id = Schema.primary_keys(@child_collection)[0]
63
+ value = Collection.get_value(@child_collection, @caller, target_relation_id, id)
64
+ filter = Filter.new(
65
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect(
66
+ [
67
+ ConditionTree::Nodes::ConditionTreeLeaf.new(id, 'Equal', value),
68
+ @permissions.get_scope(@collection)
69
+ ]
70
+ )
71
+ )
72
+
73
+ value = Collection.get_value(@collection, @caller, parent_id, relation.origin_key_target)
74
+
75
+ @child_collection.update(
76
+ @caller,
77
+ filter,
78
+ { relation.origin_key => value, relation.origin_type_field => @collection.name.gsub('__', '::') }
79
+ )
80
+ end
81
+
58
82
  def associate_many_to_many(relation, parent_id, target_relation_id)
59
83
  id = Schema.primary_keys(@child_collection)[0]
60
84
  foreign_value = Collection.get_value(@child_collection, @caller, target_relation_id, id)
@@ -28,7 +28,7 @@ module ForestAdminAgent
28
28
  filter = get_base_foreign_filter(args)
29
29
  relation = Schema.get_to_many_relation(@collection, args[:params]['relation_name'])
30
30
 
31
- if relation.type == 'OneToMany'
31
+ if relation.type == 'OneToMany' || relation.type == 'PolymorphicOneToMany'
32
32
  dissociate_or_delete_one_to_many(relation, args[:params]['relation_name'], parent_id, is_delete_mode,
33
33
  filter)
34
34
  else
@@ -47,7 +47,12 @@ module ForestAdminAgent
47
47
  if is_delete_mode
48
48
  @child_collection.delete(@caller, foreign_filter)
49
49
  else
50
- @child_collection.update(@caller, foreign_filter, { relation.origin_key => nil })
50
+ patch = if relation.type == 'PolymorphicOneToMany'
51
+ { relation.origin_key => nil, relation.origin_type_field => nil }
52
+ else
53
+ { relation.origin_key => nil }
54
+ end
55
+ @child_collection.update(@caller, foreign_filter, patch)
51
56
  end
52
57
  end
53
58
 
@@ -8,6 +8,7 @@ module ForestAdminAgent
8
8
  include ForestAdminAgent::Builder
9
9
  include ForestAdminDatasourceToolkit::Utils
10
10
  include ForestAdminDatasourceToolkit::Components::Query
11
+
11
12
  def setup_routes
12
13
  add_route(
13
14
  'forest_related_update',
@@ -26,14 +27,19 @@ module ForestAdminAgent
26
27
  relation = @collection.schema[:fields][args[:params]['relation_name']]
27
28
  parent_id = Utils::Id.unpack_id(@collection, args[:params]['id'])
28
29
 
29
- linked_id = if (id = args.dig(:params, :data, :id))
30
+ linked_id = if (id = args.dig(:params, 'data', 'id'))
30
31
  Utils::Id.unpack_id(@child_collection, id)
31
32
  end
32
33
 
33
- if relation.type == 'ManyToOne'
34
+ case relation.type
35
+ when 'ManyToOne'
34
36
  update_many_to_one(relation, parent_id, linked_id)
35
- elsif relation.type == 'OneToOne'
37
+ when 'PolymorphicManyToOne'
38
+ update_polymorphic_many_to_one(relation, parent_id, linked_id)
39
+ when 'OneToOne'
36
40
  update_one_to_one(relation, parent_id, linked_id)
41
+ when 'PolymorphicOneToOne'
42
+ update_polymorphic_one_to_one(relation, parent_id, linked_id)
37
43
  end
38
44
 
39
45
  { content: nil, status: 204 }
@@ -49,16 +55,104 @@ module ForestAdminAgent
49
55
  @collection.update(@caller, Filter.new(condition_tree: fk_owner), { relation.foreign_key => foreign_value })
50
56
  end
51
57
 
58
+ def update_polymorphic_many_to_one(relation, parent_id, linked_id)
59
+ foreign_value = if linked_id
60
+ Collection.get_value(
61
+ @child_collection,
62
+ @caller,
63
+ linked_id,
64
+ relation.foreign_key_targets[@child_collection.name]
65
+ )
66
+ end
67
+
68
+ polymorphic_type = @child_collection.name.gsub('__', '::')
69
+ fk_owner = ConditionTree::ConditionTreeFactory.match_ids(@collection, [parent_id])
70
+ @collection.update(
71
+ @caller,
72
+ Filter.new(condition_tree: fk_owner),
73
+ {
74
+ relation.foreign_key => foreign_value,
75
+ relation.foreign_key_type_field => polymorphic_type
76
+ }
77
+ )
78
+ end
79
+
80
+ def update_polymorphic_one_to_one(relation, parent_id, linked_id)
81
+ origin_value = Collection.get_value(@collection, @caller, parent_id, relation.origin_key_target)
82
+
83
+ break_old_polymorphic_one_to_one_relationship(relation, origin_value, linked_id)
84
+ create_new_polymorphic_one_to_one_relationship(relation, origin_value, linked_id)
85
+ end
86
+
52
87
  def update_one_to_one(relation, parent_id, linked_id)
53
88
  origin_value = Collection.get_value(@collection, @caller, parent_id, relation.origin_key_target)
54
89
 
55
- break_old_one_to_one_relationship(nil, relation, origin_value, linked_id)
56
- create_new_one_to_one_relationship(nil, relation, origin_value, linked_id)
90
+ break_old_one_to_one_relationship(relation, origin_value, linked_id)
91
+ create_new_one_to_one_relationship(relation, origin_value, linked_id)
57
92
  end
58
93
 
59
- def break_old_one_to_one_relationship(_scope, relation, origin_value, linked_id)
94
+ def break_old_polymorphic_one_to_one_relationship(relation, origin_value, linked_id)
60
95
  linked_id ||= []
61
96
 
97
+ old_fk_owner_filter = Filter.new(
98
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect(
99
+ [
100
+ @permissions.get_scope(@collection),
101
+ ConditionTree::Nodes::ConditionTreeBranch.new(
102
+ 'And',
103
+ [
104
+ ConditionTree::Nodes::ConditionTreeLeaf.new(
105
+ relation.origin_key,
106
+ ConditionTree::Operators::EQUAL,
107
+ origin_value
108
+ ),
109
+ ConditionTree::Nodes::ConditionTreeLeaf.new(
110
+ relation.origin_type_field,
111
+ ConditionTree::Operators::EQUAL,
112
+ @collection.name.gsub('__', '::')
113
+ )
114
+ ]
115
+ ),
116
+ # Don't set the new record's field to null
117
+ # if it's already initialized with the right value
118
+ ConditionTree::ConditionTreeFactory.match_ids(@child_collection, [linked_id]).inverse
119
+ ]
120
+ )
121
+ )
122
+
123
+ result = @child_collection.aggregate(@caller, old_fk_owner_filter, Aggregation.new(operation: 'Count'), 1)
124
+ return unless !(result[0]['value']).nil? && (result[0]['value']).positive?
125
+
126
+ # Avoids updating records to null if it's not authorized by the ORM
127
+ # and if there is no record to update (the filter returns no record)
128
+
129
+ @child_collection.update(
130
+ @caller,
131
+ old_fk_owner_filter,
132
+ { relation.origin_key => nil, relation.origin_type_field => nil }
133
+ )
134
+ end
135
+
136
+ def create_new_polymorphic_one_to_one_relationship(relation, origin_value, linked_id)
137
+ return unless linked_id
138
+
139
+ new_fk_owner = ConditionTree::ConditionTreeFactory.match_ids(@child_collection, [linked_id])
140
+
141
+ @child_collection.update(
142
+ @caller,
143
+ Filter.new(
144
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect(
145
+ [
146
+ @permissions.get_scope(@collection), new_fk_owner
147
+ ]
148
+ )
149
+ ),
150
+ { relation.origin_key => origin_value, relation.origin_type_field => @collection.name.gsub('__', '::') }
151
+ )
152
+ end
153
+
154
+ def break_old_one_to_one_relationship(relation, origin_value, linked_id)
155
+ linked_id ||= []
62
156
  old_fk_owner_filter = Filter.new(
63
157
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
64
158
  [
@@ -67,18 +161,16 @@ module ForestAdminAgent
67
161
  relation.origin_key,
68
162
  ConditionTree::Operators::EQUAL,
69
163
  origin_value
70
- )
71
- ].push(
164
+ ),
72
165
  # Don't set the new record's field to null
73
166
  # if it's already initialized with the right value
74
167
  ConditionTree::ConditionTreeFactory.match_ids(@child_collection, [linked_id]).inverse
75
- )
168
+ ]
76
169
  )
77
170
  )
78
171
 
79
172
  result = @child_collection.aggregate(@caller, old_fk_owner_filter, Aggregation.new(operation: 'Count'), 1)
80
-
81
- return unless (result[0][:value]).positive?
173
+ return unless !(result[0]['value']).nil? && (result[0]['value']).positive?
82
174
 
83
175
  # Avoids updating records to null if it's not authorized by the ORM
84
176
  # and if there is no record to update (the filter returns no record)
@@ -86,7 +178,7 @@ module ForestAdminAgent
86
178
  @child_collection.update(@caller, old_fk_owner_filter, { relation.origin_key => nil })
87
179
  end
88
180
 
89
- def create_new_one_to_one_relationship(_scope, relation, origin_value, linked_id)
181
+ def create_new_one_to_one_relationship(relation, origin_value, linked_id)
90
182
  return unless linked_id
91
183
 
92
184
  new_fk_owner = ConditionTree::ConditionTreeFactory.match_ids(@child_collection, [linked_id])
@@ -37,7 +37,7 @@ module ForestAdminAgent
37
37
  class_name: @collection.name,
38
38
  is_collection: false,
39
39
  serializer: Serializer::ForestSerializer,
40
- include: projection.relations.keys
40
+ include: projection.relations(only_keys: true)
41
41
  )
42
42
  }
43
43
  end
@@ -20,10 +20,16 @@ module ForestAdminAgent
20
20
  record = @collection.create(@caller, data)
21
21
  link_one_to_one_relations(args, record)
22
22
 
23
+ id = Utils::Id.unpack_id(@collection, record['id'], with_key: true)
24
+ filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
25
+ condition_tree: ConditionTree::ConditionTreeFactory.match_records(@collection, [id])
26
+ )
27
+ records = @collection.list(@caller, filter, ProjectionFactory.all(@collection))
28
+
23
29
  {
24
30
  name: args[:params]['collection_name'],
25
31
  content: JSONAPI::Serializer.serialize(
26
- record,
32
+ records[0],
27
33
  is_collection: false,
28
34
  class_name: @collection.name,
29
35
  serializer: Serializer::ForestSerializer
@@ -34,7 +40,7 @@ module ForestAdminAgent
34
40
  def link_one_to_one_relations(args, record)
35
41
  args[:params][:data][:relationships]&.map do |field, value|
36
42
  schema = @collection.schema[:fields][field]
37
- next unless schema.type == 'OneToOne'
43
+ next unless schema.type == 'OneToOne' || schema.type == 'PolymorphicOneToOne'
38
44
 
39
45
  id = Utils::Id.unpack_id(@collection, value['data']['id'], with_key: true)
40
46
  foreign_collection = @datasource.get_collection(schema.foreign_collection)
@@ -42,9 +48,11 @@ module ForestAdminAgent
42
48
  origin_value = record[schema.origin_key_target]
43
49
 
44
50
  # update new relation (may update zero or one records).
51
+ patch = { schema.origin_key => origin_value }
52
+ patch[schema.origin_type_field] = @collection.name.gsub('__', '::') if schema.type == 'PolymorphicOneToOne'
45
53
  condition_tree = ConditionTree::ConditionTreeFactory.match_records(foreign_collection, [id])
46
54
  filter = Filter.new(condition_tree: condition_tree)
47
- foreign_collection.update(@caller, filter, { schema.origin_key => origin_value })
55
+ foreign_collection.update(@caller, filter, patch)
48
56
  end
49
57
  end
50
58
  end
@@ -21,11 +21,13 @@ module ForestAdminAgent
21
21
 
22
22
  def type
23
23
  class_name = @options[:class_name]
24
- @@class_names[class_name] ||= class_name
24
+ @@class_names[class_name] ||= class_name.gsub('::', '__')
25
25
  end
26
26
 
27
27
  def id
28
- forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(@options[:class_name])
28
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(
29
+ @options[:class_name].gsub('::', '__')
30
+ )
29
31
  primary_keys = ForestAdminDatasourceToolkit::Utils::Schema.primary_keys(forest_collection)
30
32
  id = []
31
33
  primary_keys.each { |key| id << @object[key] }
@@ -50,7 +52,9 @@ module ForestAdminAgent
50
52
  end
51
53
 
52
54
  def attributes
53
- forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(@options[:class_name])
55
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(
56
+ @options[:class_name].gsub('::', '__')
57
+ )
54
58
  fields = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'Column' }
55
59
  fields.each { |field_name, _field| add_attribute(field_name) }
56
60
  return {} if attributes_map.nil?
@@ -110,9 +114,13 @@ module ForestAdminAgent
110
114
 
111
115
  def relationships
112
116
  datasource = ForestAdminAgent::Facades::Container.datasource
113
- forest_collection = datasource.get_collection(@options[:class_name])
114
- relations_to_many = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToMany' || field.type == 'ManyToMany' }
115
- relations_to_one = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToOne' || field.type == 'ManyToOne' }
117
+ forest_collection = datasource.get_collection(@options[:class_name].gsub('::', '__'))
118
+ relations_to_many = forest_collection.schema[:fields].select do |_field_name, field|
119
+ %w[OneToMany ManyToMany PolymorphicOneToMany].include?(field.type)
120
+ end
121
+ relations_to_one = forest_collection.schema[:fields].select do |_field_name, field|
122
+ %w[OneToOne ManyToOne PolymorphicManyToOne PolymorphicOneToOne].include?(field.type)
123
+ end
116
124
 
117
125
  relations_to_one.each { |field_name, _field| add_to_one_association(field_name) }
118
126
 
@@ -133,14 +141,24 @@ module ForestAdminAgent
133
141
  if object.nil? || object.empty?
134
142
  data[formatted_attribute_name]['data'] = nil
135
143
  else
136
- relation = datasource.get_collection(@options[:class_name]).schema[:fields][attribute_name.to_s]
144
+ relation = datasource.get_collection(@options[:class_name].gsub('::', '__'))
145
+ .schema[:fields][attribute_name.to_s]
137
146
  options = @options.clone
138
- options[:class_name] = datasource.get_collection(relation.foreign_collection).name
139
- related_object_serializer = ForestSerializer.new(object, options)
140
- data[formatted_attribute_name]['data'] = {
141
- 'type' => related_object_serializer.type.to_s,
142
- 'id' => related_object_serializer.id.to_s,
143
- }
147
+ if relation.type == 'PolymorphicManyToOne'
148
+ options[:class_name] = @object[relation.foreign_key_type_field]
149
+ related_object_serializer = ForestSerializer.new(object, options)
150
+ data[formatted_attribute_name]['data'] = {
151
+ 'type' => related_object_serializer.type.to_s,
152
+ 'id' => related_object_serializer.id.to_s,
153
+ }
154
+ else
155
+ options[:class_name] = datasource.get_collection(relation.foreign_collection).name
156
+ related_object_serializer = ForestSerializer.new(object, options)
157
+ data[formatted_attribute_name]['data'] = {
158
+ 'type' => related_object_serializer.type.to_s,
159
+ 'id' => related_object_serializer.id.to_s,
160
+ }
161
+ end
144
162
  end
145
163
  end
146
164
 
@@ -161,7 +179,7 @@ module ForestAdminAgent
161
179
  if @_include_linkages.include?(formatted_attribute_name) || attr_data[:options][:include_data]
162
180
  data[formatted_attribute_name]['data'] = []
163
181
  objects = has_many_relationship(attribute_name, attr_data) || []
164
- relation = datasource.get_collection(@options[:class_name]).schema[:fields][attribute_name.to_s]
182
+ relation = datasource.get_collection(@options[:class_name].gsub('::', '__')).schema[:fields][attribute_name.to_s]
165
183
  options = @options.clone
166
184
  options[:class_name] = datasource.get_collection(relation.foreign_collection).name
167
185
  objects.each do |obj|
@@ -173,6 +191,7 @@ module ForestAdminAgent
173
191
  end
174
192
  end
175
193
  end
194
+
176
195
  data
177
196
  end
178
197
 
@@ -25,6 +25,7 @@ module ForestAdminAgent
25
25
  object = nil
26
26
  is_collection = false
27
27
  is_valid_attr = false
28
+
28
29
  if serializer.has_one_relationships.key?(unformatted_attr_name)
29
30
  is_valid_attr = true
30
31
  attr_data = serializer.has_one_relationships[unformatted_attr_name]
@@ -58,8 +59,15 @@ module ForestAdminAgent
58
59
  # If it is not set, that indicates that this is an inner path and not a leaf and will
59
60
  # be followed by the recursion below.
60
61
  objects.each do |obj|
61
- relation = ForestAdminAgent::Facades::Container.datasource.get_collection(options[:class_name]).schema[:fields][attribute_name]
62
- relation_class_name = ForestAdminAgent::Facades::Container.datasource.get_collection(relation.foreign_collection).name
62
+ relation = ForestAdminAgent::Facades::Container.datasource
63
+ .get_collection(options[:class_name].gsub('::', '__'))
64
+ .schema[:fields][attribute_name]
65
+ if relation.type == 'PolymorphicManyToOne'
66
+ relation_class_name = root_object[relation.foreign_key_type_field]
67
+ else
68
+ relation_class_name = ForestAdminAgent::Facades::Container.datasource.get_collection(relation.foreign_collection).name
69
+ end
70
+
63
71
  option_relation = options.clone
64
72
  option_relation[:class_name] = relation_class_name
65
73
  obj_serializer = JSONAPI::Serializer.find_serializer(obj, option_relation)
@@ -203,6 +211,7 @@ module ForestAdminAgent
203
211
  # of the internal special merging logic.
204
212
  find_recursive_relationships(obj, inclusion_tree, relationship_data, passthrough_options)
205
213
  end
214
+
206
215
  result['included'] = relationship_data.map do |_, data|
207
216
  included_passthrough_options = {}
208
217
  included_passthrough_options[:base_url] = passthrough_options[:base_url]
@@ -216,6 +225,7 @@ module ForestAdminAgent
216
225
  serialize_primary(data[:object], included_passthrough_options)
217
226
  end
218
227
  end
228
+
219
229
  result
220
230
  end
221
231
  end
@@ -60,7 +60,13 @@ module ForestAdminAgent
60
60
 
61
61
  fields = fields.split(',').map do |field_name|
62
62
  column = collection.schema[:fields][field_name.strip]
63
- column.type == 'Column' ? field_name.strip : "#{field_name.strip}:#{args[:params][:fields][field_name.strip]}"
63
+ if column.type == 'Column'
64
+ field_name.strip
65
+ elsif column.type == 'PolymorphicManyToOne'
66
+ "#{field_name.strip}:*"
67
+ else
68
+ "#{field_name.strip}:#{args[:params][:fields][field_name.strip]}"
69
+ end
64
70
  end
65
71
 
66
72
  Projection.new(fields)
@@ -4,20 +4,22 @@ module ForestAdminAgent
4
4
  class GeneratorField
5
5
  RELATION_MAP = {
6
6
  'ManyToMany' => 'BelongsToMany',
7
+ 'PolymorphicManyToOne' => 'BelongsTo',
7
8
  'ManyToOne' => 'BelongsTo',
9
+ 'PolymorphicOneToMany' => 'HasMany',
8
10
  'OneToMany' => 'HasMany',
11
+ 'PolymorphicOneToOne' => 'HasOne',
9
12
  'OneToOne' => 'HasOne'
10
13
  }.freeze
11
14
 
12
15
  def self.build_schema(collection, name)
13
16
  type = collection.schema[:fields][name].type
14
17
 
15
- case type
16
- when 'Column'
17
- schema = build_column_schema(collection, name)
18
- when 'ManyToOne', 'OneToMany', 'ManyToMany', 'OneToOne'
19
- schema = build_relation_schema(collection, name)
20
- end
18
+ schema = if type == 'Column'
19
+ build_column_schema(collection, name)
20
+ else
21
+ build_relation_schema(collection, name)
22
+ end
21
23
 
22
24
  schema.sort_by { |k, _v| k }.to_h
23
25
  end
@@ -151,29 +153,53 @@ module ForestAdminAgent
151
153
  )
152
154
  end
153
155
 
156
+ def build_polymorphic_many_to_one_schema(relation, base_schema)
157
+ base_schema.merge(
158
+ {
159
+ type: 'Number', # default or take first foreign_key_targets ??,
160
+ defaultValue: nil,
161
+ isFilterable: false,
162
+ isPrimaryKey: false,
163
+ isRequired: false,
164
+ isReadOnly: false,
165
+ isSortable: false,
166
+ validations: [],
167
+ reference: "#{base_schema[:field]}.id",
168
+ polymorphic_referenced_models: relation.foreign_collections
169
+ }
170
+ )
171
+ end
172
+
154
173
  def build_relation_schema(collection, name)
155
174
  relation = collection.schema[:fields][name]
156
- foreign_collection = collection.datasource.get_collection(relation.foreign_collection)
157
-
158
175
  relation_schema = {
159
176
  field: name,
160
177
  enums: nil,
161
178
  integration: nil,
162
179
  isReadOnly: nil,
163
180
  isVirtual: false,
164
- inverseOf: ForestAdminDatasourceToolkit::Utils::Collection.get_inverse_relation(collection, name),
165
181
  relationship: RELATION_MAP[relation.type]
166
182
  }
167
183
 
168
- case relation.type
169
- when 'ManyToMany'
170
- build_many_to_many_schema(relation, collection, foreign_collection, relation_schema)
171
- when 'OneToMany'
172
- build_one_to_many_schema(relation, collection, foreign_collection, relation_schema)
173
- when 'OneToOne'
174
- build_one_to_one_schema(relation, collection, foreign_collection, relation_schema)
175
- when 'ManyToOne'
176
- build_many_to_one_schema(relation, collection, foreign_collection, relation_schema)
184
+ if relation.type == 'PolymorphicManyToOne'
185
+ relation_schema[:inverseOf] = collection.name
186
+ build_polymorphic_many_to_one_schema(relation, relation_schema)
187
+ else
188
+ relation_schema[:inverseOf] = ForestAdminDatasourceToolkit::Utils::Collection.get_inverse_relation(
189
+ collection,
190
+ name
191
+ )
192
+ foreign_collection = collection.datasource.get_collection(relation.foreign_collection)
193
+ case relation.type
194
+ when 'ManyToMany'
195
+ build_many_to_many_schema(relation, collection, foreign_collection, relation_schema)
196
+ when 'OneToMany', 'PolymorphicOneToMany'
197
+ build_one_to_many_schema(relation, collection, foreign_collection, relation_schema)
198
+ when 'OneToOne', 'PolymorphicOneToOne'
199
+ build_one_to_one_schema(relation, collection, foreign_collection, relation_schema)
200
+ when 'ManyToOne'
201
+ build_many_to_one_schema(relation, collection, foreign_collection, relation_schema)
202
+ end
177
203
  end
178
204
  end
179
205
  end
@@ -7,7 +7,7 @@ module ForestAdminAgent
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "agent-ruby"
9
9
 
10
- LIANA_VERSION = "1.0.0-beta.61"
10
+ LIANA_VERSION = "1.0.0-beta.62"
11
11
 
12
12
  def self.get_serialized_schema(datasource)
13
13
  schema_path = Facades::Container.cache(:schema_path)
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.0.0-beta.61"
2
+ VERSION = "1.0.0-beta.62"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.beta.61
4
+ version: 1.0.0.pre.beta.62
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2024-07-26 00:00:00.000000000 Z
12
+ date: 2024-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport