forest_admin_agent 1.0.0.pre.beta.60 → 1.0.0.pre.beta.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d139f75a88e0da6b4900f761ed7f8cb6ff127da70e16c6b046ff8e689bdf362
4
- data.tar.gz: 00fd69796e962e847b7cb4ef01941b723ceeb66b23415aed9eee2fa2cab54a92
3
+ metadata.gz: 8094394fa87dd1d0c83fac337a16804b9aefa3592bf3398b4ae859a45de031af
4
+ data.tar.gz: 38438b2a1f495a1b448796e742189103a8180bb8322735ae5b88708557da505b
5
5
  SHA512:
6
- metadata.gz: 8ad28b9ead8aca8e508bd6f3c59b9dd625d78f04fc02e58f574f065870137ca364e8b2efc99b75187001a105ed061a1197cf22f2a48b83cfeef5ae2879b76878
7
- data.tar.gz: 47d0f533c7b88121faa68aa7512b9439d424ed9234fddbbed4f02745b9a4071cce62962d9833fe87f871a1da5a38856be748e017c3cc5d74ef4a44bfd84d8514
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.60"
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.60"
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.60
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-08 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