jsonapi-resources 0.10.7 → 0.11.0.beta2
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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +39 -2
- data/lib/generators/jsonapi/controller_generator.rb +2 -0
- data/lib/generators/jsonapi/resource_generator.rb +2 -0
- data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +3 -2
- data/lib/jsonapi/active_relation/join_manager.rb +30 -18
- data/lib/jsonapi/active_relation/join_manager_v10.rb +305 -0
- data/lib/jsonapi/active_relation_retrieval.rb +885 -0
- data/lib/jsonapi/active_relation_retrieval_v09.rb +715 -0
- data/lib/jsonapi/{active_relation_resource.rb → active_relation_retrieval_v10.rb} +113 -135
- data/lib/jsonapi/acts_as_resource_controller.rb +49 -49
- data/lib/jsonapi/cached_response_fragment.rb +4 -2
- data/lib/jsonapi/callbacks.rb +2 -0
- data/lib/jsonapi/compiled_json.rb +2 -0
- data/lib/jsonapi/configuration.rb +35 -15
- data/lib/jsonapi/error.rb +2 -0
- data/lib/jsonapi/error_codes.rb +2 -0
- data/lib/jsonapi/exceptions.rb +2 -0
- data/lib/jsonapi/formatter.rb +2 -0
- data/lib/jsonapi/include_directives.rb +77 -19
- data/lib/jsonapi/link_builder.rb +2 -0
- data/lib/jsonapi/mime_types.rb +6 -10
- data/lib/jsonapi/naive_cache.rb +2 -0
- data/lib/jsonapi/operation.rb +2 -0
- data/lib/jsonapi/operation_result.rb +2 -0
- data/lib/jsonapi/paginator.rb +2 -17
- data/lib/jsonapi/path.rb +2 -0
- data/lib/jsonapi/path_segment.rb +4 -2
- data/lib/jsonapi/processor.rb +100 -153
- data/lib/jsonapi/relationship.rb +89 -35
- data/lib/jsonapi/{request_parser.rb → request.rb} +157 -164
- data/lib/jsonapi/resource.rb +7 -2
- data/lib/jsonapi/{basic_resource.rb → resource_common.rb} +187 -88
- data/lib/jsonapi/resource_controller.rb +2 -0
- data/lib/jsonapi/resource_controller_metal.rb +2 -0
- data/lib/jsonapi/resource_fragment.rb +17 -15
- data/lib/jsonapi/resource_identity.rb +6 -0
- data/lib/jsonapi/resource_serializer.rb +20 -4
- data/lib/jsonapi/resource_set.rb +36 -16
- data/lib/jsonapi/resource_tree.rb +191 -0
- data/lib/jsonapi/resources/railtie.rb +3 -1
- data/lib/jsonapi/resources/version.rb +3 -1
- data/lib/jsonapi/response_document.rb +4 -2
- data/lib/jsonapi/routing_ext.rb +4 -2
- data/lib/jsonapi/simple_resource.rb +13 -0
- data/lib/jsonapi-resources.rb +10 -4
- data/lib/tasks/check_upgrade.rake +3 -1
- metadata +47 -15
- data/lib/jsonapi/resource_id_tree.rb +0 -112
data/lib/jsonapi/processor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JSONAPI
|
2
4
|
class Processor
|
3
5
|
include Callbacks
|
@@ -49,7 +51,7 @@ module JSONAPI
|
|
49
51
|
|
50
52
|
verified_filters = resource_klass.verify_filters(filters, context)
|
51
53
|
|
52
|
-
|
54
|
+
options = {
|
53
55
|
context: context,
|
54
56
|
sort_criteria: sort_criteria,
|
55
57
|
paginator: paginator,
|
@@ -58,20 +60,18 @@ module JSONAPI
|
|
58
60
|
include_directives: include_directives
|
59
61
|
}
|
60
62
|
|
61
|
-
resource_set = find_resource_set(
|
62
|
-
include_directives,
|
63
|
-
find_options)
|
63
|
+
resource_set = find_resource_set(include_directives, options)
|
64
64
|
|
65
|
-
resource_set.populate!(serializer, context,
|
65
|
+
resource_set.populate!(serializer, context, options)
|
66
66
|
|
67
67
|
page_options = result_options
|
68
|
-
if (top_level_meta_include_record_count || (paginator && paginator.requires_record_count))
|
68
|
+
if (JSONAPI.configuration.top_level_meta_include_record_count || (paginator && paginator.class.requires_record_count))
|
69
69
|
page_options[:record_count] = resource_klass.count(verified_filters,
|
70
70
|
context: context,
|
71
71
|
include_directives: include_directives)
|
72
72
|
end
|
73
73
|
|
74
|
-
if (top_level_meta_include_page_count && paginator && page_options[:record_count])
|
74
|
+
if (JSONAPI.configuration.top_level_meta_include_page_count && paginator && page_options[:record_count])
|
75
75
|
page_options[:page_count] = paginator ? paginator.calculate_page_count(page_options[:record_count]) : 1
|
76
76
|
end
|
77
77
|
|
@@ -79,7 +79,7 @@ module JSONAPI
|
|
79
79
|
page_options[:pagination_params] = paginator.links_page_params(page_options.merge(fetched_resources: resource_set))
|
80
80
|
end
|
81
81
|
|
82
|
-
|
82
|
+
JSONAPI::ResourcesSetOperationResult.new(:ok, resource_set, page_options)
|
83
83
|
end
|
84
84
|
|
85
85
|
def show
|
@@ -90,26 +90,25 @@ module JSONAPI
|
|
90
90
|
|
91
91
|
key = resource_klass.verify_key(id, context)
|
92
92
|
|
93
|
-
|
93
|
+
options = {
|
94
94
|
context: context,
|
95
95
|
fields: fields,
|
96
96
|
filters: { resource_klass._primary_key => key },
|
97
97
|
include_directives: include_directives
|
98
98
|
}
|
99
99
|
|
100
|
-
resource_set = find_resource_set(
|
101
|
-
include_directives,
|
102
|
-
find_options)
|
100
|
+
resource_set = find_resource_set(include_directives, options)
|
103
101
|
|
104
102
|
fail JSONAPI::Exceptions::RecordNotFound.new(id) if resource_set.resource_klasses.empty?
|
105
|
-
resource_set.populate!(serializer, context,
|
103
|
+
resource_set.populate!(serializer, context, options)
|
106
104
|
|
107
|
-
|
105
|
+
JSONAPI::ResourceSetOperationResult.new(:ok, resource_set, result_options)
|
108
106
|
end
|
109
107
|
|
110
108
|
def show_relationship
|
111
109
|
parent_key = params[:parent_key]
|
112
110
|
relationship_type = params[:relationship_type].to_sym
|
111
|
+
relationship = resource_klass._relationship(relationship_type)
|
113
112
|
paginator = params[:paginator]
|
114
113
|
sort_criteria = params[:sort_criteria]
|
115
114
|
include_directives = params[:include_directives]
|
@@ -117,25 +116,26 @@ module JSONAPI
|
|
117
116
|
|
118
117
|
parent_resource = resource_klass.find_by_key(parent_key, context: context)
|
119
118
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
119
|
+
options = {
|
120
|
+
context: context,
|
121
|
+
sort_criteria: sort_criteria,
|
122
|
+
paginator: paginator,
|
123
|
+
fields: fields,
|
124
|
+
include_directives: include_directives
|
126
125
|
}
|
127
126
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
127
|
+
resource_tree = find_related_resource_tree(
|
128
|
+
parent_resource,
|
129
|
+
relationship,
|
130
|
+
options,
|
131
|
+
nil
|
132
|
+
)
|
133
|
+
|
134
|
+
JSONAPI::RelationshipOperationResult.new(:ok,
|
135
|
+
parent_resource,
|
136
|
+
relationship,
|
137
|
+
resource_tree.fragments.keys,
|
138
|
+
result_options)
|
139
139
|
end
|
140
140
|
|
141
141
|
def show_related_resource
|
@@ -146,11 +146,11 @@ module JSONAPI
|
|
146
146
|
serializer = params[:serializer]
|
147
147
|
fields = params[:fields]
|
148
148
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
options = {
|
150
|
+
context: context,
|
151
|
+
fields: fields,
|
152
|
+
filters: {},
|
153
|
+
include_directives: include_directives
|
154
154
|
}
|
155
155
|
|
156
156
|
source_resource = source_klass.find_by_key(source_id, context: context, fields: fields)
|
@@ -158,11 +158,11 @@ module JSONAPI
|
|
158
158
|
resource_set = find_related_resource_set(source_resource,
|
159
159
|
relationship_type,
|
160
160
|
include_directives,
|
161
|
-
|
161
|
+
options)
|
162
162
|
|
163
|
-
resource_set.populate!(serializer, context,
|
163
|
+
resource_set.populate!(serializer, context, options)
|
164
164
|
|
165
|
-
|
165
|
+
JSONAPI::ResourceSetOperationResult.new(:ok, resource_set, result_options)
|
166
166
|
end
|
167
167
|
|
168
168
|
def show_related_resources
|
@@ -178,8 +178,8 @@ module JSONAPI
|
|
178
178
|
|
179
179
|
verified_filters = resource_klass.verify_filters(filters, context)
|
180
180
|
|
181
|
-
|
182
|
-
filters:
|
181
|
+
options = {
|
182
|
+
filters: verified_filters,
|
183
183
|
sort_criteria: sort_criteria,
|
184
184
|
paginator: paginator,
|
185
185
|
fields: fields,
|
@@ -192,38 +192,40 @@ module JSONAPI
|
|
192
192
|
resource_set = find_related_resource_set(source_resource,
|
193
193
|
relationship_type,
|
194
194
|
include_directives,
|
195
|
-
|
195
|
+
options)
|
196
196
|
|
197
|
-
resource_set.populate!(serializer, context,
|
197
|
+
resource_set.populate!(serializer, context, options)
|
198
198
|
|
199
199
|
opts = result_options
|
200
|
-
if ((top_level_meta_include_record_count) ||
|
201
|
-
|
202
|
-
|
200
|
+
if ((JSONAPI.configuration.top_level_meta_include_record_count) ||
|
201
|
+
(paginator && paginator.class.requires_record_count) ||
|
202
|
+
(JSONAPI.configuration.top_level_meta_include_page_count))
|
203
|
+
|
204
|
+
relationship = source_resource.class._relationship(relationship_type)
|
203
205
|
|
204
206
|
opts[:record_count] = source_resource.class.count_related(
|
205
|
-
|
206
|
-
|
207
|
-
|
207
|
+
source_resource,
|
208
|
+
relationship,
|
209
|
+
options)
|
208
210
|
end
|
209
211
|
|
210
|
-
if (top_level_meta_include_page_count && opts[:record_count])
|
212
|
+
if (JSONAPI.configuration.top_level_meta_include_page_count && opts[:record_count])
|
211
213
|
opts[:page_count] = paginator.calculate_page_count(opts[:record_count])
|
212
214
|
end
|
213
215
|
|
214
216
|
opts[:pagination_params] = if paginator && JSONAPI.configuration.top_level_links_include_pagination
|
215
217
|
page_options = {}
|
216
|
-
page_options[:record_count] = opts[:record_count] if paginator.requires_record_count
|
218
|
+
page_options[:record_count] = opts[:record_count] if paginator.class.requires_record_count
|
217
219
|
paginator.links_page_params(page_options.merge(fetched_resources: resource_set))
|
218
220
|
else
|
219
221
|
{}
|
220
222
|
end
|
221
223
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
224
|
+
JSONAPI::RelatedResourcesSetOperationResult.new(:ok,
|
225
|
+
source_resource,
|
226
|
+
relationship_type,
|
227
|
+
resource_set,
|
228
|
+
opts)
|
227
229
|
end
|
228
230
|
|
229
231
|
def create_resource
|
@@ -235,20 +237,18 @@ module JSONAPI
|
|
235
237
|
resource = resource_klass.create(context)
|
236
238
|
result = resource.replace_fields(data)
|
237
239
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
240
|
+
options = {
|
241
|
+
context: context,
|
242
|
+
fields: fields,
|
243
|
+
filters: { resource_klass._primary_key => resource.id },
|
244
|
+
include_directives: include_directives
|
243
245
|
}
|
244
246
|
|
245
|
-
resource_set = find_resource_set(
|
246
|
-
include_directives,
|
247
|
-
find_options)
|
247
|
+
resource_set = find_resource_set(include_directives, options)
|
248
248
|
|
249
|
-
resource_set.populate!(serializer, context,
|
249
|
+
resource_set.populate!(serializer, context, options)
|
250
250
|
|
251
|
-
|
251
|
+
JSONAPI::ResourceSetOperationResult.new((result == :completed ? :created : :accepted), resource_set, result_options)
|
252
252
|
end
|
253
253
|
|
254
254
|
def remove_resource
|
@@ -257,7 +257,7 @@ module JSONAPI
|
|
257
257
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
258
258
|
result = resource.remove
|
259
259
|
|
260
|
-
|
260
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
261
261
|
end
|
262
262
|
|
263
263
|
def replace_fields
|
@@ -272,20 +272,18 @@ module JSONAPI
|
|
272
272
|
|
273
273
|
result = resource.replace_fields(data)
|
274
274
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
275
|
+
options = {
|
276
|
+
context: context,
|
277
|
+
fields: fields,
|
278
|
+
filters: { resource_klass._primary_key => resource.id },
|
279
|
+
include_directives: include_directives
|
280
280
|
}
|
281
281
|
|
282
|
-
resource_set = find_resource_set(
|
283
|
-
include_directives,
|
284
|
-
find_options)
|
282
|
+
resource_set = find_resource_set(include_directives, options)
|
285
283
|
|
286
|
-
resource_set.populate!(serializer, context,
|
284
|
+
resource_set.populate!(serializer, context, options)
|
287
285
|
|
288
|
-
|
286
|
+
JSONAPI::ResourceSetOperationResult.new((result == :completed ? :ok : :accepted), resource_set, result_options)
|
289
287
|
end
|
290
288
|
|
291
289
|
def replace_to_one_relationship
|
@@ -296,7 +294,7 @@ module JSONAPI
|
|
296
294
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
297
295
|
result = resource.replace_to_one_link(relationship_type, key_value)
|
298
296
|
|
299
|
-
|
297
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
300
298
|
end
|
301
299
|
|
302
300
|
def replace_polymorphic_to_one_relationship
|
@@ -308,7 +306,7 @@ module JSONAPI
|
|
308
306
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
309
307
|
result = resource.replace_polymorphic_to_one_link(relationship_type, key_value, key_type)
|
310
308
|
|
311
|
-
|
309
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
312
310
|
end
|
313
311
|
|
314
312
|
def create_to_many_relationships
|
@@ -319,7 +317,7 @@ module JSONAPI
|
|
319
317
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
320
318
|
result = resource.create_to_many_links(relationship_type, data)
|
321
319
|
|
322
|
-
|
320
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
323
321
|
end
|
324
322
|
|
325
323
|
def replace_to_many_relationships
|
@@ -330,7 +328,7 @@ module JSONAPI
|
|
330
328
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
331
329
|
result = resource.replace_to_many_links(relationship_type, data)
|
332
330
|
|
333
|
-
|
331
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
334
332
|
end
|
335
333
|
|
336
334
|
def remove_to_many_relationships
|
@@ -347,7 +345,7 @@ module JSONAPI
|
|
347
345
|
complete = false
|
348
346
|
end
|
349
347
|
end
|
350
|
-
|
348
|
+
JSONAPI::OperationResult.new(complete ? :no_content : :accepted, result_options)
|
351
349
|
end
|
352
350
|
|
353
351
|
def remove_to_one_relationship
|
@@ -357,7 +355,7 @@ module JSONAPI
|
|
357
355
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
358
356
|
result = resource.remove_to_one_link(relationship_type)
|
359
357
|
|
360
|
-
|
358
|
+
JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted, result_options)
|
361
359
|
end
|
362
360
|
|
363
361
|
def result_options
|
@@ -366,99 +364,48 @@ module JSONAPI
|
|
366
364
|
options
|
367
365
|
end
|
368
366
|
|
369
|
-
def find_resource_set(
|
370
|
-
include_related = include_directives
|
367
|
+
def find_resource_set(include_directives, options)
|
368
|
+
include_related = include_directives[:include_related] if include_directives
|
371
369
|
|
372
|
-
|
370
|
+
resource_tree = find_resource_tree(options, include_related)
|
373
371
|
|
374
|
-
JSONAPI::ResourceSet.new(
|
372
|
+
JSONAPI::ResourceSet.new(resource_tree)
|
375
373
|
end
|
376
374
|
|
377
375
|
def find_related_resource_set(resource, relationship_name, include_directives, options)
|
378
|
-
include_related = include_directives
|
379
|
-
|
380
|
-
resource_id_tree = find_resource_id_tree_from_resource_relationship(resource, relationship_name, options, include_related)
|
376
|
+
include_related = include_directives[:include_related] if include_directives
|
381
377
|
|
382
|
-
|
383
|
-
end
|
384
|
-
|
385
|
-
def top_level_meta_include_record_count
|
386
|
-
JSONAPI.configuration.top_level_meta_include_record_count
|
387
|
-
end
|
378
|
+
resource_tree = find_resource_tree_from_relationship(resource, relationship_name, options, include_related)
|
388
379
|
|
389
|
-
|
390
|
-
JSONAPI.configuration.top_level_meta_include_page_count
|
380
|
+
JSONAPI::ResourceSet.new(resource_tree)
|
391
381
|
end
|
392
382
|
|
393
|
-
|
394
|
-
def find_related_resource_id_tree(resource_klass, source_id, relationship_name, find_options, include_related)
|
395
|
-
options = find_options.except(:include_directives)
|
383
|
+
def find_resource_tree(options, include_related)
|
396
384
|
options[:cache] = resource_klass.caching?
|
397
385
|
|
398
|
-
fragments = resource_klass.
|
399
|
-
|
400
|
-
primary_resource_id_tree = PrimaryResourceIdTree.new
|
401
|
-
primary_resource_id_tree.add_resource_fragments(fragments, include_related)
|
402
|
-
|
403
|
-
load_included(resource_klass, primary_resource_id_tree, include_related, options)
|
404
|
-
|
405
|
-
primary_resource_id_tree
|
386
|
+
fragments = resource_klass.find_fragments(options[:filters], options)
|
387
|
+
PrimaryResourceTree.new(fragments: fragments, include_related: include_related, options: options)
|
406
388
|
end
|
407
389
|
|
408
|
-
def
|
409
|
-
options =
|
390
|
+
def find_related_resource_tree(parent_resource, relationship, options, include_related)
|
391
|
+
options = options.except(:include_directives)
|
410
392
|
options[:cache] = resource_klass.caching?
|
411
393
|
|
412
|
-
|
413
|
-
|
414
|
-
primary_resource_id_tree = PrimaryResourceIdTree.new
|
415
|
-
primary_resource_id_tree.add_resource_fragments(fragments, include_related)
|
394
|
+
parent_resource_fragment = parent_resource.fragment(primary: true)
|
416
395
|
|
417
|
-
|
418
|
-
|
419
|
-
primary_resource_id_tree
|
396
|
+
fragments = resource_klass.find_related_fragments(parent_resource_fragment, relationship, options)
|
397
|
+
PrimaryResourceTree.new(fragments: fragments, include_related: include_related, options: options)
|
420
398
|
end
|
421
399
|
|
422
|
-
def
|
400
|
+
def find_resource_tree_from_relationship(resource, relationship_name, options, include_related)
|
423
401
|
relationship = resource.class._relationship(relationship_name)
|
424
402
|
|
425
|
-
options =
|
403
|
+
options = options.except(:include_directives)
|
426
404
|
options[:cache] = relationship.resource_klass.caching?
|
427
405
|
|
428
|
-
fragments = resource.class.find_related_fragments(
|
429
|
-
|
430
|
-
primary_resource_id_tree = PrimaryResourceIdTree.new
|
431
|
-
primary_resource_id_tree.add_resource_fragments(fragments, include_related)
|
406
|
+
fragments = resource.class.find_related_fragments(resource.fragment, relationship, options)
|
432
407
|
|
433
|
-
|
434
|
-
|
435
|
-
primary_resource_id_tree
|
436
|
-
end
|
437
|
-
|
438
|
-
def load_included(resource_klass, source_resource_id_tree, include_related, options)
|
439
|
-
source_rids = source_resource_id_tree.fragments.keys
|
440
|
-
|
441
|
-
include_related.try(:each_key) do |key|
|
442
|
-
relationship = resource_klass._relationship(key)
|
443
|
-
relationship_name = relationship.name.to_sym
|
444
|
-
|
445
|
-
find_related_resource_options = options.except(:filters, :sort_criteria, :paginator)
|
446
|
-
find_related_resource_options[:sort_criteria] = relationship.resource_klass.default_sort
|
447
|
-
find_related_resource_options[:cache] = resource_klass.caching?
|
448
|
-
|
449
|
-
related_fragments = resource_klass.find_included_fragments(
|
450
|
-
source_rids, relationship_name, find_related_resource_options
|
451
|
-
)
|
452
|
-
|
453
|
-
related_resource_id_tree = source_resource_id_tree.fetch_related_resource_id_tree(relationship)
|
454
|
-
related_resource_id_tree.add_resource_fragments(related_fragments, include_related[key][include_related])
|
455
|
-
|
456
|
-
# Now recursively get the related resources for the currently found resources
|
457
|
-
load_included(relationship.resource_klass,
|
458
|
-
related_resource_id_tree,
|
459
|
-
include_related[relationship_name][:include_related],
|
460
|
-
options)
|
461
|
-
end
|
408
|
+
PrimaryResourceTree.new(fragments: fragments, include_related: include_related, options: options)
|
462
409
|
end
|
463
410
|
end
|
464
411
|
end
|