jsonapi-resources 0.10.6 → 0.11.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +39 -2
  4. data/lib/generators/jsonapi/controller_generator.rb +2 -0
  5. data/lib/generators/jsonapi/resource_generator.rb +2 -0
  6. data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +3 -2
  7. data/lib/jsonapi/active_relation/join_manager.rb +30 -18
  8. data/lib/jsonapi/active_relation/join_manager_v10.rb +305 -0
  9. data/lib/jsonapi/active_relation_retrieval.rb +885 -0
  10. data/lib/jsonapi/active_relation_retrieval_v09.rb +715 -0
  11. data/lib/jsonapi/{active_relation_resource.rb → active_relation_retrieval_v10.rb} +113 -135
  12. data/lib/jsonapi/acts_as_resource_controller.rb +49 -49
  13. data/lib/jsonapi/cached_response_fragment.rb +4 -2
  14. data/lib/jsonapi/callbacks.rb +2 -0
  15. data/lib/jsonapi/compiled_json.rb +2 -0
  16. data/lib/jsonapi/configuration.rb +35 -15
  17. data/lib/jsonapi/error.rb +2 -0
  18. data/lib/jsonapi/error_codes.rb +2 -0
  19. data/lib/jsonapi/exceptions.rb +2 -0
  20. data/lib/jsonapi/formatter.rb +2 -0
  21. data/lib/jsonapi/include_directives.rb +77 -19
  22. data/lib/jsonapi/link_builder.rb +2 -0
  23. data/lib/jsonapi/mime_types.rb +6 -10
  24. data/lib/jsonapi/naive_cache.rb +2 -0
  25. data/lib/jsonapi/operation.rb +2 -0
  26. data/lib/jsonapi/operation_result.rb +2 -0
  27. data/lib/jsonapi/paginator.rb +2 -0
  28. data/lib/jsonapi/path.rb +2 -0
  29. data/lib/jsonapi/path_segment.rb +4 -2
  30. data/lib/jsonapi/processor.rb +95 -140
  31. data/lib/jsonapi/relationship.rb +89 -35
  32. data/lib/jsonapi/{request_parser.rb → request.rb} +157 -164
  33. data/lib/jsonapi/resource.rb +7 -2
  34. data/lib/jsonapi/{basic_resource.rb → resource_common.rb} +187 -88
  35. data/lib/jsonapi/resource_controller.rb +2 -0
  36. data/lib/jsonapi/resource_controller_metal.rb +2 -0
  37. data/lib/jsonapi/resource_fragment.rb +17 -15
  38. data/lib/jsonapi/resource_identity.rb +6 -0
  39. data/lib/jsonapi/resource_serializer.rb +20 -4
  40. data/lib/jsonapi/resource_set.rb +36 -16
  41. data/lib/jsonapi/resource_tree.rb +191 -0
  42. data/lib/jsonapi/resources/railtie.rb +3 -1
  43. data/lib/jsonapi/resources/version.rb +3 -1
  44. data/lib/jsonapi/response_document.rb +4 -2
  45. data/lib/jsonapi/routing_ext.rb +4 -2
  46. data/lib/jsonapi/simple_resource.rb +13 -0
  47. data/lib/jsonapi-resources.rb +10 -4
  48. data/lib/tasks/check_upgrade.rake +3 -1
  49. metadata +47 -15
  50. data/lib/jsonapi/resource_id_tree.rb +0 -112
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
- class RequestParser
4
+ class Request
3
5
  attr_accessor :fields, :include, :filters, :sort_criteria, :errors, :controller_module_path,
4
6
  :context, :paginator, :source_klass, :source_id,
5
- :include_directives, :params, :warnings, :server_error_callbacks
7
+ :include_directives, :params, :warnings, :server_error_callbacks, :operations
6
8
 
7
9
  def initialize(params = nil, options = {})
8
10
  @params = params
@@ -18,33 +20,25 @@ module JSONAPI
18
20
  @errors = []
19
21
  @warnings = []
20
22
  @server_error_callbacks = options.fetch(:server_error_callbacks, [])
23
+ @operations = []
24
+
25
+ setup_operations(params)
21
26
  end
22
27
 
23
28
  def error_object_overrides
24
29
  {}
25
30
  end
26
31
 
27
- def each(_response_document)
28
- operation = setup_base_op(params)
29
- if @errors.any?
30
- fail JSONAPI::Exceptions::Errors.new(@errors)
31
- else
32
- yield operation
33
- end
34
- rescue ActionController::ParameterMissing => e
35
- fail JSONAPI::Exceptions::ParameterMissing.new(e.param, error_object_overrides)
36
- end
37
-
38
32
  def transactional?
39
33
  case params[:action]
40
- when 'index', 'show_related_resource', 'index_related_resources', 'show', 'show_relationship'
41
- return false
42
- else
43
- return true
34
+ when 'index', 'show_related_resource', 'index_related_resources', 'show', 'show_relationship'
35
+ false
36
+ else
37
+ true
44
38
  end
45
39
  end
46
40
 
47
- def setup_base_op(params)
41
+ def setup_operations(params)
48
42
  return if params.nil?
49
43
 
50
44
  resource_klass = Resource.resource_klass_for(params[:controller]) if params[:controller]
@@ -68,15 +62,15 @@ module JSONAPI
68
62
  sort_criteria = parse_sort_criteria(resource_klass, params[:sort])
69
63
  paginator = parse_pagination(resource_klass, params[:page])
70
64
 
71
- JSONAPI::Operation.new(
72
- :find,
73
- resource_klass,
74
- context: context,
75
- filters: filters,
76
- include_directives: include_directives,
77
- sort_criteria: sort_criteria,
78
- paginator: paginator,
79
- fields: fields
65
+ @operations << JSONAPI::Operation.new(
66
+ :find,
67
+ resource_klass,
68
+ context: context,
69
+ filters: filters,
70
+ include_directives: include_directives,
71
+ sort_criteria: sort_criteria,
72
+ paginator: paginator,
73
+ fields: fields
80
74
  )
81
75
  end
82
76
 
@@ -90,15 +84,15 @@ module JSONAPI
90
84
 
91
85
  relationship_type = params[:relationship].to_sym
92
86
 
93
- JSONAPI::Operation.new(
94
- :show_related_resource,
95
- resource_klass,
96
- context: @context,
97
- relationship_type: relationship_type,
98
- source_klass: source_klass,
99
- source_id: source_id,
100
- fields: fields,
101
- include_directives: include_directives
87
+ @operations << JSONAPI::Operation.new(
88
+ :show_related_resource,
89
+ resource_klass,
90
+ context: @context,
91
+ relationship_type: relationship_type,
92
+ source_klass: source_klass,
93
+ source_id: source_id,
94
+ fields: fields,
95
+ include_directives: include_directives
102
96
  )
103
97
  end
104
98
 
@@ -114,18 +108,18 @@ module JSONAPI
114
108
  paginator = parse_pagination(resource_klass, params[:page])
115
109
  relationship_type = params[:relationship]
116
110
 
117
- JSONAPI::Operation.new(
118
- :show_related_resources,
119
- resource_klass,
120
- context: @context,
121
- relationship_type: relationship_type,
122
- source_klass: source_klass,
123
- source_id: source_id,
124
- filters: filters,
125
- sort_criteria: sort_criteria,
126
- paginator: paginator,
127
- fields: fields,
128
- include_directives: include_directives
111
+ @operations << JSONAPI::Operation.new(
112
+ :show_related_resources,
113
+ resource_klass,
114
+ context: @context,
115
+ relationship_type: relationship_type,
116
+ source_klass: source_klass,
117
+ source_id: source_id,
118
+ filters: filters,
119
+ sort_criteria: sort_criteria,
120
+ paginator: paginator,
121
+ fields: fields,
122
+ include_directives: include_directives
129
123
  )
130
124
  end
131
125
 
@@ -135,14 +129,14 @@ module JSONAPI
135
129
  include_directives = parse_include_directives(resource_klass, params[:include])
136
130
  id = params[:id]
137
131
 
138
- JSONAPI::Operation.new(
139
- :show,
140
- resource_klass,
141
- context: @context,
142
- id: id,
143
- include_directives: include_directives,
144
- fields: fields,
145
- allowed_resources: params[:allowed_resources]
132
+ @operations << JSONAPI::Operation.new(
133
+ :show,
134
+ resource_klass,
135
+ context: @context,
136
+ id: id,
137
+ include_directives: include_directives,
138
+ fields: fields,
139
+ allowed_resources: params[:allowed_resources]
146
140
  )
147
141
  end
148
142
 
@@ -155,17 +149,17 @@ module JSONAPI
155
149
  sort_criteria = parse_sort_criteria(resource_klass, params[:sort])
156
150
  paginator = parse_pagination(resource_klass, params[:page])
157
151
 
158
- JSONAPI::Operation.new(
159
- :show_relationship,
160
- resource_klass,
161
- context: @context,
162
- relationship_type: relationship_type,
163
- parent_key: resource_klass.verify_key(parent_key),
164
- filters: filters,
165
- sort_criteria: sort_criteria,
166
- paginator: paginator,
167
- fields: fields,
168
- include_directives: include_directives
152
+ @operations << JSONAPI::Operation.new(
153
+ :show_relationship,
154
+ resource_klass,
155
+ context: @context,
156
+ relationship_type: relationship_type,
157
+ parent_key: resource_klass.verify_key(parent_key),
158
+ filters: filters,
159
+ sort_criteria: sort_criteria,
160
+ paginator: paginator,
161
+ fields: fields,
162
+ include_directives: include_directives
169
163
  )
170
164
  end
171
165
 
@@ -183,14 +177,14 @@ module JSONAPI
183
177
 
184
178
  data = parse_params(resource_klass, data, resource_klass.creatable_fields(@context))
185
179
 
186
- JSONAPI::Operation.new(
187
- :create_resource,
188
- resource_klass,
189
- context: @context,
190
- data: data,
191
- fields: fields,
192
- include_directives: include_directives,
193
- warnings: @warnings
180
+ @operations << JSONAPI::Operation.new(
181
+ :create_resource,
182
+ resource_klass,
183
+ context: @context,
184
+ data: data,
185
+ fields: fields,
186
+ include_directives: include_directives,
187
+ warnings: @warnings
194
188
  )
195
189
  end
196
190
 
@@ -225,25 +219,25 @@ module JSONAPI
225
219
 
226
220
  verify_type(data[:type], resource_klass)
227
221
 
228
- JSONAPI::Operation.new(
229
- :replace_fields,
230
- resource_klass,
231
- context: @context,
232
- resource_id: resource_id,
233
- data: parse_params(resource_klass, data, resource_klass.updatable_fields(@context)),
234
- fields: fields,
235
- include_directives: include_directives,
236
- warnings: @warnings
222
+ @operations << JSONAPI::Operation.new(
223
+ :replace_fields,
224
+ resource_klass,
225
+ context: @context,
226
+ resource_id: resource_id,
227
+ data: parse_params(resource_klass, data, resource_klass.updatable_fields(@context)),
228
+ fields: fields,
229
+ include_directives: include_directives,
230
+ warnings: @warnings
237
231
  )
238
232
  end
239
233
 
240
234
  def setup_destroy_action(params, resource_klass)
241
235
  resolve_singleton_id(params, resource_klass)
242
- JSONAPI::Operation.new(
243
- :remove_resource,
244
- resource_klass,
245
- context: @context,
246
- resource_id: resource_klass.verify_key(params.require(:id), @context))
236
+ @operations << JSONAPI::Operation.new(
237
+ :remove_resource,
238
+ resource_klass,
239
+ context: @context,
240
+ resource_id: resource_klass.verify_key(params.require(:id), @context))
247
241
  end
248
242
 
249
243
  def setup_destroy_relationship_action(params, resource_klass)
@@ -349,7 +343,6 @@ module JSONAPI
349
343
  else
350
344
  fail JSONAPI::Exceptions::InvalidInclude.new(format_key(resource_klass._type), include_parts.first)
351
345
  end
352
- true
353
346
  end
354
347
 
355
348
  def parse_include_directives(resource_klass, raw_include)
@@ -458,19 +451,19 @@ module JSONAPI
458
451
  def parse_to_one_links_object(raw)
459
452
  if raw.nil?
460
453
  return {
461
- type: nil,
462
- id: nil
454
+ type: nil,
455
+ id: nil
463
456
  }
464
457
  end
465
458
 
466
459
  if !(raw.is_a?(Hash) || raw.is_a?(ActionController::Parameters)) ||
467
- raw.keys.length != 2 || !(raw.key?('type') && raw.key?('id'))
460
+ raw.keys.length != 2 || !(raw.key?('type') && raw.key?('id'))
468
461
  fail JSONAPI::Exceptions::InvalidLinksObject.new(error_object_overrides)
469
462
  end
470
463
 
471
464
  {
472
- type: unformat_key(raw['type']).to_s,
473
- id: raw['id']
465
+ type: unformat_key(raw['type']).to_s,
466
+ id: raw['id']
474
467
  }
475
468
  end
476
469
 
@@ -499,33 +492,33 @@ module JSONAPI
499
492
 
500
493
  params.each do |key, value|
501
494
  case key.to_s
502
- when 'relationships'
503
- value.each do |link_key, link_value|
504
- param = unformat_key(link_key)
505
- relationship = resource_klass._relationship(param)
506
-
507
- if relationship.is_a?(JSONAPI::Relationship::ToOne)
508
- checked_to_one_relationships[param] = parse_to_one_relationship(resource_klass, link_value, relationship)
509
- elsif relationship.is_a?(JSONAPI::Relationship::ToMany)
510
- parse_to_many_relationship(resource_klass, link_value, relationship) do |result_val|
511
- checked_to_many_relationships[param] = result_val
512
- end
495
+ when 'relationships'
496
+ value.each do |link_key, link_value|
497
+ param = unformat_key(link_key)
498
+ relationship = resource_klass._relationship(param)
499
+
500
+ if relationship.is_a?(JSONAPI::Relationship::ToOne)
501
+ checked_to_one_relationships[param] = parse_to_one_relationship(resource_klass, link_value, relationship)
502
+ elsif relationship.is_a?(JSONAPI::Relationship::ToMany)
503
+ parse_to_many_relationship(resource_klass, link_value, relationship) do |result_val|
504
+ checked_to_many_relationships[param] = result_val
513
505
  end
514
506
  end
515
- when 'id'
516
- checked_attributes['id'] = unformat_value(resource_klass, :id, value)
517
- when 'attributes'
518
- value.each do |key, value|
519
- param = unformat_key(key)
520
- checked_attributes[param] = unformat_value(resource_klass, param, value)
521
- end
507
+ end
508
+ when 'id'
509
+ checked_attributes['id'] = unformat_value(resource_klass, :id, value)
510
+ when 'attributes'
511
+ value.each do |key, value|
512
+ param = unformat_key(key)
513
+ checked_attributes[param] = unformat_value(resource_klass, param, value)
514
+ end
522
515
  end
523
516
  end
524
517
 
525
- return {
526
- 'attributes' => checked_attributes,
527
- 'to_one' => checked_to_one_relationships,
528
- 'to_many' => checked_to_many_relationships
518
+ {
519
+ 'attributes' => checked_attributes,
520
+ 'to_one' => checked_to_one_relationships,
521
+ 'to_many' => checked_to_many_relationships
529
522
  }.deep_transform_keys { |key| unformat_key(key) }
530
523
  end
531
524
 
@@ -584,7 +577,7 @@ module JSONAPI
584
577
  end
585
578
 
586
579
  relationship_ids = relationship_resource_klass.verify_keys(keys, @context)
587
- polymorphic_results << { type: type, ids: relationship_ids }
580
+ polymorphic_results << { type: type, ids: relationship_ids }
588
581
  end
589
582
 
590
583
  add_result.call polymorphic_results
@@ -612,45 +605,45 @@ module JSONAPI
612
605
 
613
606
  params.each do |key, value|
614
607
  case key.to_s
615
- when 'relationships'
616
- value.keys.each do |links_key|
617
- unless formatted_allowed_fields.include?(links_key.to_sym)
618
- if JSONAPI.configuration.raise_if_parameters_not_allowed
619
- fail JSONAPI::Exceptions::ParameterNotAllowed.new(links_key, error_object_overrides)
620
- else
621
- params_not_allowed.push(links_key)
622
- value.delete links_key
623
- end
624
- end
625
- end
626
- when 'attributes'
627
- value.each do |attr_key, _attr_value|
628
- unless formatted_allowed_fields.include?(attr_key.to_sym)
629
- if JSONAPI.configuration.raise_if_parameters_not_allowed
630
- fail JSONAPI::Exceptions::ParameterNotAllowed.new(attr_key, error_object_overrides)
631
- else
632
- params_not_allowed.push(attr_key)
633
- value.delete attr_key
634
- end
608
+ when 'relationships'
609
+ value.keys.each do |links_key|
610
+ unless formatted_allowed_fields.include?(links_key.to_sym)
611
+ if JSONAPI.configuration.raise_if_parameters_not_allowed
612
+ fail JSONAPI::Exceptions::ParameterNotAllowed.new(links_key, error_object_overrides)
613
+ else
614
+ params_not_allowed.push(links_key)
615
+ value.delete links_key
635
616
  end
636
617
  end
637
- when 'type'
638
- when 'id'
639
- unless formatted_allowed_fields.include?(:id)
618
+ end
619
+ when 'attributes'
620
+ value.each do |attr_key, _attr_value|
621
+ unless formatted_allowed_fields.include?(attr_key.to_sym)
640
622
  if JSONAPI.configuration.raise_if_parameters_not_allowed
641
- fail JSONAPI::Exceptions::ParameterNotAllowed.new(:id, error_object_overrides)
623
+ fail JSONAPI::Exceptions::ParameterNotAllowed.new(attr_key, error_object_overrides)
642
624
  else
643
- params_not_allowed.push(:id)
644
- params.delete :id
625
+ params_not_allowed.push(attr_key)
626
+ value.delete attr_key
645
627
  end
646
628
  end
647
- else
629
+ end
630
+ when 'type'
631
+ when 'id'
632
+ unless formatted_allowed_fields.include?(:id)
648
633
  if JSONAPI.configuration.raise_if_parameters_not_allowed
649
- fail JSONAPI::Exceptions::ParameterNotAllowed.new(key, error_object_overrides)
634
+ fail JSONAPI::Exceptions::ParameterNotAllowed.new(:id, error_object_overrides)
650
635
  else
651
- params_not_allowed.push(key)
652
- params.delete key
636
+ params_not_allowed.push(:id)
637
+ params.delete :id
653
638
  end
639
+ end
640
+ else
641
+ if JSONAPI.configuration.raise_if_parameters_not_allowed
642
+ fail JSONAPI::Exceptions::ParameterNotAllowed.new(key, error_object_overrides)
643
+ else
644
+ params_not_allowed.push(key)
645
+ params.delete key
646
+ end
654
647
  end
655
648
  end
656
649
 
@@ -666,22 +659,22 @@ module JSONAPI
666
659
 
667
660
  def parse_add_relationship_operation(resource_klass, verified_params, relationship, parent_key)
668
661
  if relationship.is_a?(JSONAPI::Relationship::ToMany)
669
- return JSONAPI::Operation.new(
670
- :create_to_many_relationships,
671
- resource_klass,
672
- context: @context,
673
- resource_id: parent_key,
674
- relationship_type: relationship.name,
675
- data: verified_params[:to_many].values[0]
662
+ @operations << JSONAPI::Operation.new(
663
+ :create_to_many_relationships,
664
+ resource_klass,
665
+ context: @context,
666
+ resource_id: parent_key,
667
+ relationship_type: relationship.name,
668
+ data: verified_params[:to_many].values[0]
676
669
  )
677
670
  end
678
671
  end
679
672
 
680
673
  def parse_update_relationship_operation(resource_klass, verified_params, relationship, parent_key)
681
674
  options = {
682
- context: @context,
683
- resource_id: parent_key,
684
- relationship_type: relationship.name
675
+ context: @context,
676
+ resource_id: parent_key,
677
+ relationship_type: relationship.name
685
678
  }
686
679
 
687
680
  if relationship.is_a?(JSONAPI::Relationship::ToOne)
@@ -702,23 +695,23 @@ module JSONAPI
702
695
  operation_type = :replace_to_many_relationships
703
696
  end
704
697
 
705
- JSONAPI::Operation.new(operation_type, resource_klass, options)
698
+ @operations << JSONAPI::Operation.new(operation_type, resource_klass, options)
706
699
  end
707
700
 
708
701
  def parse_remove_relationship_operation(resource_klass, params, relationship, parent_key)
709
702
  operation_base_args = [resource_klass].push(
710
- context: @context,
711
- resource_id: parent_key,
712
- relationship_type: relationship.name
703
+ context: @context,
704
+ resource_id: parent_key,
705
+ relationship_type: relationship.name
713
706
  )
714
707
 
715
708
  if relationship.is_a?(JSONAPI::Relationship::ToMany)
716
709
  operation_args = operation_base_args.dup
717
710
  keys = params[:to_many].values[0]
718
711
  operation_args[1] = operation_args[1].merge(associated_keys: keys)
719
- JSONAPI::Operation.new(:remove_to_many_relationships, *operation_args)
712
+ @operations << JSONAPI::Operation.new(:remove_to_many_relationships, *operation_args)
720
713
  else
721
- JSONAPI::Operation.new(:remove_to_one_relationship, *operation_base_args)
714
+ @operations << JSONAPI::Operation.new(:remove_to_one_relationship, *operation_base_args)
722
715
  end
723
716
  end
724
717
 
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
- class Resource < ActiveRelationResource
4
+ class Resource
5
+ include ResourceCommon
3
6
  root_resource
7
+ abstract
8
+ immutable
4
9
  end
5
- end
10
+ end