forest_admin_agent 1.0.0.pre.beta.27 → 1.0.0.pre.beta.28

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: d5a1222f5af1bf778087d4b388f224d8802cb52f4aa59a203d608145f11a0920
4
- data.tar.gz: a63be1a15f8778eb1a7766ebcc099ef66a39f8804059bb6b1fe9783c45cec718
3
+ metadata.gz: e2ae114be4b54df0354aca036cdc18ca08ab1c78b72d6975b3002179cea93a18
4
+ data.tar.gz: fd369183191175beb32c586bd98f2c67ccd21a7438e5b41741c0a5f0667985ce
5
5
  SHA512:
6
- metadata.gz: b395ae4c2e8a0d5c1a5f974170dc863af79f969d0118b703b97dde95e92b119f007bdc5373bac86fd271029f69493baca613f0608e031cfb7b1cf0284514bfc0
7
- data.tar.gz: 90a0a84788e6e13aa7a324463aee664c44f28952e22625335bbf95f7534ccccced3f8e397834658e1bb1154e6aa8756e39408fa3f5ad4c4e84885d5f360a6513
6
+ metadata.gz: 2465a1fb919eccdd5daef0183cf0bc371d312b6fa8462dfcbb6096e587376efad479184269b32617143e53d321c0208b361d99af66eabbeea299c6050dd87e3c
7
+ data.tar.gz: e8ee04c59cbc81fa1b38478e40507d94434b68e2be5009a7b6403731ac117793b9aa462c567704125a7a96264eee46123c7c915979f91ec20042fea2620dc361
@@ -34,6 +34,7 @@ module ForestAdminAgent
34
34
  name: args[:params]['collection_name'],
35
35
  content: JSONAPI::Serializer.serialize(
36
36
  records,
37
+ class_name: @collection.name,
37
38
  is_collection: true,
38
39
  serializer: Serializer::ForestSerializer,
39
40
  include: projection.relations.keys,
@@ -50,6 +50,7 @@ module ForestAdminAgent
50
50
  content: JSONAPI::Serializer.serialize(
51
51
  records,
52
52
  is_collection: true,
53
+ class_name: @child_collection.name,
53
54
  serializer: Serializer::ForestSerializer,
54
55
  include: projection.relations.keys
55
56
  )
@@ -34,6 +34,7 @@ module ForestAdminAgent
34
34
  name: args[:params]['collection_name'],
35
35
  content: JSONAPI::Serializer.serialize(
36
36
  records[0],
37
+ class_name: @collection.name,
37
38
  is_collection: false,
38
39
  serializer: Serializer::ForestSerializer,
39
40
  include: projection.relations.keys
@@ -25,6 +25,7 @@ module ForestAdminAgent
25
25
  content: JSONAPI::Serializer.serialize(
26
26
  record,
27
27
  is_collection: false,
28
+ class_name: @collection.name,
28
29
  serializer: Serializer::ForestSerializer
29
30
  )
30
31
  }
@@ -33,6 +33,7 @@ module ForestAdminAgent
33
33
  content: JSONAPI::Serializer.serialize(
34
34
  records[0],
35
35
  is_collection: false,
36
+ class_name: @collection.name,
36
37
  serializer: Serializer::ForestSerializer
37
38
  )
38
39
  }
@@ -20,8 +20,17 @@ module ForestAdminAgent
20
20
  end
21
21
 
22
22
  def type
23
- class_name = object.class.name
24
- @@class_names[class_name] ||= class_name.demodulize.underscore.freeze
23
+ class_name = @options[:class_name]
24
+ @@class_names[class_name] ||= class_name
25
+ end
26
+
27
+ def id
28
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(@options[:class_name])
29
+ primary_keys = ForestAdminDatasourceToolkit::Utils::Schema.primary_keys(forest_collection)
30
+ id = []
31
+ primary_keys.each { |key| id << @object[key] }
32
+
33
+ id.join('|')
25
34
  end
26
35
 
27
36
  def format_name(attribute_name)
@@ -41,7 +50,7 @@ module ForestAdminAgent
41
50
  end
42
51
 
43
52
  def attributes
44
- forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(object.class.name.demodulize.underscore)
53
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(@options[:class_name])
45
54
  fields = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'Column' }
46
55
  fields.each { |field_name, _field| add_attribute(field_name) }
47
56
  return {} if attributes_map.nil?
@@ -61,11 +70,7 @@ module ForestAdminAgent
61
70
  instance_eval(&attr_or_block)
62
71
  else
63
72
  # Default behavior, call a method by the name of the attribute.
64
- begin
65
- object.try(attr_or_block)
66
- rescue
67
- nil
68
- end
73
+ object[attr_or_block]
69
74
  end
70
75
  end
71
76
 
@@ -104,7 +109,8 @@ module ForestAdminAgent
104
109
  end
105
110
 
106
111
  def relationships
107
- forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(object.class.name.demodulize.underscore)
112
+ datasource = ForestAdminAgent::Facades::Container.datasource
113
+ forest_collection = datasource.get_collection(@options[:class_name])
108
114
  relations_to_many = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToMany' || field.type == 'ManyToMany' }
109
115
  relations_to_one = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToOne' || field.type == 'ManyToOne' }
110
116
 
@@ -124,10 +130,13 @@ module ForestAdminAgent
124
130
  end
125
131
 
126
132
  object = has_one_relationship(attribute_name, attr_data)
127
- if object.nil?
133
+ if object.nil? || object.empty?
128
134
  data[formatted_attribute_name]['data'] = nil
129
135
  else
130
- related_object_serializer = ForestSerializer.new(object, @options)
136
+ relation = datasource.get_collection(@options[:class_name]).schema[:fields][attribute_name.to_s]
137
+ options = @options.clone
138
+ options[:class_name] = datasource.get_collection(relation.foreign_collection).name
139
+ related_object_serializer = ForestSerializer.new(object, options)
131
140
  data[formatted_attribute_name]['data'] = {
132
141
  'type' => related_object_serializer.type.to_s,
133
142
  'id' => related_object_serializer.id.to_s,
@@ -152,6 +161,9 @@ module ForestAdminAgent
152
161
  if @_include_linkages.include?(formatted_attribute_name) || attr_data[:options][:include_data]
153
162
  data[formatted_attribute_name]['data'] = []
154
163
  objects = has_many_relationship(attribute_name, attr_data) || []
164
+ relation = datasource.get_collection(@options[:class_name]).schema[:fields][attribute_name.to_s]
165
+ options = @options.clone
166
+ options[:class_name] = datasource.get_collection(relation.foreign_collection).name
155
167
  objects.each do |obj|
156
168
  related_object_serializer = JSONAPI::Serializer.find_serializer(obj, @options)
157
169
  data[formatted_attribute_name]['data'] << {
@@ -48,7 +48,7 @@ module ForestAdminAgent
48
48
  end
49
49
 
50
50
  # We're finding relationships for compound documents, so skip anything that doesn't exist.
51
- next if object.nil?
51
+ next if object.nil? || object.empty?
52
52
 
53
53
  # Full linkage: a request for comments.author MUST automatically include comments
54
54
  # in the response.
@@ -58,6 +58,8 @@ module ForestAdminAgent
58
58
  # If it is not set, that indicates that this is an inner path and not a leaf and will
59
59
  # be followed by the recursion below.
60
60
  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
61
63
  obj_serializer = JSONAPI::Serializer.find_serializer(obj, options)
62
64
  # Use keys of ['posts', '1'] for the results to enforce uniqueness.
63
65
  # Spec: A compound document MUST NOT include more than one resource object for each
@@ -82,7 +84,8 @@ module ForestAdminAgent
82
84
  # so merge the include_linkages each time we see it to load all the relevant linkages.
83
85
  current_child_includes += (results[key] && results[key][:include_linkages]) || []
84
86
  current_child_includes.uniq!
85
- results[key] = { object: obj, include_linkages: current_child_includes }
87
+
88
+ results[key] = { object: obj, include_linkages: current_child_includes, class_name: relation_class_name }
86
89
  end
87
90
  end
88
91
 
@@ -96,6 +99,123 @@ module ForestAdminAgent
96
99
  end
97
100
  nil
98
101
  end
102
+
103
+ def self.serialize(objects, options = {})
104
+ # Normalize option strings to symbols.
105
+ options[:is_collection] = options.delete('is_collection') || options[:is_collection] || false
106
+ options[:include] = options.delete('include') || options[:include]
107
+ options[:serializer] = options.delete('serializer') || options[:serializer]
108
+ options[:namespace] = options.delete('namespace') || options[:namespace]
109
+ options[:context] = options.delete('context') || options[:context] || {}
110
+ options[:skip_collection_check] = options.delete('skip_collection_check') || options[:skip_collection_check] || false
111
+ options[:base_url] = options.delete('base_url') || options[:base_url]
112
+ options[:jsonapi] = options.delete('jsonapi') || options[:jsonapi]
113
+ options[:meta] = options.delete('meta') || options[:meta]
114
+ options[:links] = options.delete('links') || options[:links]
115
+ options[:fields] = options.delete('fields') || options[:fields] || {}
116
+
117
+ # Deprecated: use serialize_errors method instead
118
+ options[:errors] = options.delete('errors') || options[:errors]
119
+
120
+ # Normalize includes.
121
+ includes = options[:include]
122
+ includes = (includes.is_a?(String) ? includes.split(',') : includes).uniq if includes
123
+
124
+ # Transforms input so that the comma-separated fields are separate symbols in array
125
+ # and keys are stringified
126
+ # Example:
127
+ # {posts: 'title,author,long_comments'} => {'posts' => [:title, :author, :long_comments]}
128
+ # {posts: ['title', 'author', 'long_comments'} => {'posts' => [:title, :author, :long_comments]}
129
+ #
130
+ fields = {}
131
+ # Normalize fields to accept a comma-separated string or an array of strings.
132
+ options[:fields].map do |type, whitelisted_fields|
133
+ whitelisted_fields = [whitelisted_fields] if whitelisted_fields.is_a?(Symbol)
134
+ whitelisted_fields = whitelisted_fields.split(',') if whitelisted_fields.is_a?(String)
135
+ fields[type.to_s] = whitelisted_fields.map(&:to_sym)
136
+ end
137
+
138
+ # An internal-only structure that is passed through serializers as they are created.
139
+ passthrough_options = {
140
+ context: options[:context],
141
+ serializer: options[:serializer],
142
+ namespace: options[:namespace],
143
+ include: includes,
144
+ fields: fields,
145
+ base_url: options[:base_url],
146
+ class_name: options[:class_name]
147
+ }
148
+
149
+ if !options[:skip_collection_check] && options[:is_collection] && !objects.respond_to?(:each)
150
+ raise JSONAPI::Serializer::AmbiguousCollectionError.new(
151
+ 'Attempted to serialize a single object as a collection.')
152
+ end
153
+
154
+ # Automatically include linkage data for any relation that is also included.
155
+ if includes
156
+ include_linkages = includes.map { |key| key.to_s.split('.').first }
157
+ passthrough_options[:include_linkages] = include_linkages
158
+ end
159
+
160
+ # Spec: Primary data MUST be either:
161
+ # - a single resource object or null, for requests that target single resources.
162
+ # - an array of resource objects or an empty array ([]), for resource collections.
163
+ # http://jsonapi.org/format/#document-structure-top-level
164
+ if options[:is_collection] && !objects.any?
165
+ primary_data = []
166
+ elsif !options[:is_collection] && objects.nil?
167
+ primary_data = nil
168
+ elsif options[:is_collection]
169
+ # Have object collection.
170
+ primary_data = serialize_primary_multi(objects, passthrough_options)
171
+ else
172
+ # Duck-typing check for a collection being passed without is_collection true.
173
+ # We always must be told if serializing a collection because the JSON:API spec distinguishes
174
+ # how to serialize null single resources vs. empty collections.
175
+ if !options[:skip_collection_check] && objects.is_a?(Array)
176
+ raise JSONAPI::Serializer::AmbiguousCollectionError.new(
177
+ 'Must provide `is_collection: true` to `serialize` when serializing collections.')
178
+ end
179
+ # Have single object.
180
+ primary_data = serialize_primary(objects, passthrough_options)
181
+ end
182
+ result = {
183
+ 'data' => primary_data,
184
+ }
185
+ result['jsonapi'] = options[:jsonapi] if options[:jsonapi]
186
+ result['meta'] = options[:meta] if options[:meta]
187
+ result['links'] = options[:links] if options[:links]
188
+ result['errors'] = options[:errors] if options[:errors]
189
+
190
+ # If 'include' relationships are given, recursively find and include each object.
191
+ if includes
192
+ relationship_data = {}
193
+ inclusion_tree = parse_relationship_paths(includes)
194
+
195
+ # Given all the primary objects (either the single root object or collection of objects),
196
+ # recursively search and find related associations that were specified as includes.
197
+ objects = options[:is_collection] ? objects.to_a : [objects]
198
+ objects.compact.each do |obj|
199
+ # Use the mutability of relationship_data as the return datastructure to take advantage
200
+ # of the internal special merging logic.
201
+ find_recursive_relationships(obj, inclusion_tree, relationship_data, passthrough_options)
202
+ end
203
+
204
+ result['included'] = relationship_data.map do |_, data|
205
+ included_passthrough_options = {}
206
+ included_passthrough_options[:base_url] = passthrough_options[:base_url]
207
+ included_passthrough_options[:context] = passthrough_options[:context]
208
+ included_passthrough_options[:fields] = passthrough_options[:fields]
209
+ included_passthrough_options[:serializer] = find_serializer_class(data[:object], options)
210
+ included_passthrough_options[:namespace] = passthrough_options[:namespace]
211
+ included_passthrough_options[:include_linkages] = data[:include_linkages]
212
+ included_passthrough_options[:class_name] = data[:class_name]
213
+
214
+ serialize_primary(data[:object], included_passthrough_options)
215
+ end
216
+ end
217
+ result
218
+ end
99
219
  end
100
220
  end
101
221
  end
@@ -7,7 +7,7 @@ module ForestAdminAgent
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "forest-rails"
9
9
 
10
- LIANA_VERSION = "1.0.0-beta.27"
10
+ LIANA_VERSION = "1.0.0-beta.28"
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.27"
2
+ VERSION = "1.0.0-beta.28"
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.27
4
+ version: 1.0.0.pre.beta.28
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-01-02 00:00:00.000000000 Z
12
+ date: 2024-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport