jsonapi-resources 0.3.3 → 0.4.0
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/README.md +274 -102
- data/jsonapi-resources.gemspec +1 -0
- data/lib/jsonapi-resources.rb +15 -0
- data/lib/jsonapi/active_record_operations_processor.rb +21 -10
- data/lib/jsonapi/acts_as_resource_controller.rb +175 -0
- data/lib/jsonapi/configuration.rb +11 -0
- data/lib/jsonapi/error_codes.rb +7 -4
- data/lib/jsonapi/exceptions.rb +23 -15
- data/lib/jsonapi/formatter.rb +5 -5
- data/lib/jsonapi/include_directives.rb +67 -0
- data/lib/jsonapi/operation.rb +185 -65
- data/lib/jsonapi/operation_result.rb +38 -5
- data/lib/jsonapi/operation_results.rb +33 -0
- data/lib/jsonapi/operations_processor.rb +49 -9
- data/lib/jsonapi/paginator.rb +31 -17
- data/lib/jsonapi/request.rb +347 -163
- data/lib/jsonapi/resource.rb +159 -56
- data/lib/jsonapi/resource_controller.rb +1 -234
- data/lib/jsonapi/resource_serializer.rb +55 -69
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +87 -0
- data/lib/jsonapi/routing_ext.rb +17 -11
- data/test/controllers/controller_test.rb +602 -326
- data/test/fixtures/active_record.rb +96 -6
- data/test/fixtures/line_items.yml +7 -1
- data/test/fixtures/numeros_telefone.yml +3 -0
- data/test/fixtures/purchase_orders.yml +6 -0
- data/test/integration/requests/request_test.rb +129 -60
- data/test/integration/routes/routes_test.rb +17 -17
- data/test/test_helper.rb +23 -5
- data/test/unit/jsonapi_request/jsonapi_request_test.rb +48 -0
- data/test/unit/operation/operations_processor_test.rb +242 -54
- data/test/unit/resource/resource_test.rb +108 -2
- data/test/unit/serializer/include_directives_test.rb +108 -0
- data/test/unit/serializer/response_document_test.rb +61 -0
- data/test/unit/serializer/serializer_test.rb +679 -520
- metadata +26 -2
data/lib/jsonapi/operation.rb
CHANGED
@@ -1,162 +1,282 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
class Operation
|
3
|
+
attr_reader :resource_klass, :options, :transactional
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(resource_klass)
|
5
|
+
def initialize(resource_klass, options = {})
|
7
6
|
@resource_klass = resource_klass
|
7
|
+
@options = options
|
8
|
+
@transactional = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply(context)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class FindOperation < Operation
|
16
|
+
attr_reader :filters, :include_directives, :sort_criteria, :paginator
|
17
|
+
|
18
|
+
def initialize(resource_klass, options = {})
|
19
|
+
@filters = options[:filters]
|
20
|
+
@include_directives = options[:include_directives]
|
21
|
+
@sort_criteria = options.fetch(:sort_criteria, [])
|
22
|
+
@paginator = options[:paginator]
|
23
|
+
super(resource_klass, false)
|
24
|
+
end
|
25
|
+
|
26
|
+
def apply(context)
|
27
|
+
resource_records = @resource_klass.find(@resource_klass.verify_filters(@filters, context),
|
28
|
+
context: context,
|
29
|
+
include_directives: @include_directives,
|
30
|
+
sort_criteria: @sort_criteria,
|
31
|
+
paginator: @paginator)
|
32
|
+
|
33
|
+
return JSONAPI::ResourcesOperationResult.new(:ok, resource_records)
|
34
|
+
|
35
|
+
rescue JSONAPI::Exceptions::Error => e
|
36
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ShowOperation < Operation
|
41
|
+
attr_reader :id, :include_directives
|
42
|
+
|
43
|
+
def initialize(resource_klass, options = {})
|
44
|
+
@id = options.fetch(:id)
|
45
|
+
@include_directives = options[:include_directives]
|
46
|
+
@transactional = false
|
47
|
+
super(resource_klass, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def apply(context)
|
51
|
+
key = @resource_klass.verify_key(@id, context)
|
52
|
+
|
53
|
+
resource_record = resource_klass.find_by_key(key,
|
54
|
+
context: context,
|
55
|
+
include_directives: @include_directives)
|
56
|
+
|
57
|
+
return JSONAPI::ResourceOperationResult.new(:ok, resource_record)
|
58
|
+
|
59
|
+
rescue JSONAPI::Exceptions::Error => e
|
60
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class ShowAssociationOperation < Operation
|
65
|
+
attr_reader :parent_key, :association_type
|
66
|
+
|
67
|
+
def initialize(resource_klass, options = {})
|
68
|
+
@parent_key = options.fetch(:parent_key)
|
69
|
+
@association_type = options.fetch(:association_type)
|
70
|
+
@transactional = false
|
71
|
+
super(resource_klass, options)
|
8
72
|
end
|
9
73
|
|
10
74
|
def apply(context)
|
75
|
+
parent_resource = resource_klass.find_by_key(@parent_key, context: context)
|
76
|
+
|
77
|
+
return JSONAPI::LinksObjectOperationResult.new(:ok,
|
78
|
+
parent_resource,
|
79
|
+
resource_klass._association(@association_type))
|
80
|
+
|
81
|
+
rescue JSONAPI::Exceptions::Error => e
|
82
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class ShowRelatedResourceOperation < Operation
|
87
|
+
attr_reader :source_klass, :source_id, :association_type
|
88
|
+
|
89
|
+
def initialize(resource_klass, options = {})
|
90
|
+
@source_klass = options.fetch(:source_klass)
|
91
|
+
@source_id = options.fetch(:source_id)
|
92
|
+
@association_type = options.fetch(:association_type)
|
93
|
+
@transactional = false
|
94
|
+
super(resource_klass, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
def apply(context)
|
98
|
+
source_resource = @source_klass.find_by_key(@source_id, context: context)
|
99
|
+
|
100
|
+
related_resource = source_resource.send(@association_type)
|
101
|
+
|
102
|
+
return JSONAPI::ResourceOperationResult.new(:ok, related_resource)
|
103
|
+
|
104
|
+
rescue JSONAPI::Exceptions::Error => e
|
105
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class ShowRelatedResourcesOperation < Operation
|
110
|
+
attr_reader :source_klass, :source_id, :association_type, :filters, :sort_criteria, :paginator
|
111
|
+
|
112
|
+
def initialize(resource_klass, options = {})
|
113
|
+
@source_klass = options.fetch(:source_klass)
|
114
|
+
@source_id = options.fetch(:source_id)
|
115
|
+
@association_type = options.fetch(:association_type)
|
116
|
+
@filters = options[:filters]
|
117
|
+
@sort_criteria = options[:sort_criteria]
|
118
|
+
@paginator = options[:paginator]
|
119
|
+
@transactional = false
|
120
|
+
super(resource_klass, options)
|
121
|
+
end
|
122
|
+
|
123
|
+
def apply(context)
|
124
|
+
source_resource = @source_klass.find_by_key(@source_id, context: context)
|
125
|
+
|
126
|
+
related_resource = source_resource.send(@association_type,
|
127
|
+
{
|
128
|
+
filters: @filters,
|
129
|
+
sort_criteria: @sort_criteria,
|
130
|
+
paginator: @paginator
|
131
|
+
})
|
132
|
+
|
133
|
+
return JSONAPI::ResourceOperationResult.new(:ok, related_resource)
|
134
|
+
|
135
|
+
rescue JSONAPI::Exceptions::Error => e
|
136
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
11
137
|
end
|
12
138
|
end
|
13
139
|
|
14
140
|
class CreateResourceOperation < Operation
|
15
|
-
attr_reader :
|
141
|
+
attr_reader :data
|
16
142
|
|
17
|
-
def initialize(resource_klass,
|
18
|
-
@
|
19
|
-
super(resource_klass)
|
143
|
+
def initialize(resource_klass, options = {})
|
144
|
+
@data = options.fetch(:data)
|
145
|
+
super(resource_klass, options)
|
20
146
|
end
|
21
147
|
|
22
148
|
def apply(context)
|
23
149
|
resource = @resource_klass.create(context)
|
24
|
-
resource.replace_fields(@
|
150
|
+
result = resource.replace_fields(@data)
|
25
151
|
|
26
|
-
return JSONAPI::
|
152
|
+
return JSONAPI::ResourceOperationResult.new((result == :completed ? :created : :accepted), resource)
|
27
153
|
|
28
154
|
rescue JSONAPI::Exceptions::Error => e
|
29
|
-
return JSONAPI::
|
155
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
30
156
|
end
|
31
157
|
end
|
32
158
|
|
33
159
|
class RemoveResourceOperation < Operation
|
34
160
|
attr_reader :resource_id
|
35
|
-
def initialize(resource_klass,
|
36
|
-
@resource_id = resource_id
|
37
|
-
super(resource_klass)
|
161
|
+
def initialize(resource_klass, options = {})
|
162
|
+
@resource_id = options.fetch(:resource_id)
|
163
|
+
super(resource_klass, options)
|
38
164
|
end
|
39
165
|
|
40
166
|
def apply(context)
|
41
167
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
42
|
-
resource.remove
|
168
|
+
result = resource.remove
|
43
169
|
|
44
|
-
return JSONAPI::OperationResult.new(:no_content)
|
170
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
45
171
|
|
46
|
-
rescue ActiveRecord::DeleteRestrictionError => e
|
47
|
-
record_locked_error = JSONAPI::Exceptions::RecordLocked.new(e.message)
|
48
|
-
return JSONAPI::OperationResult.new(record_locked_error.errors[0].code, nil, record_locked_error.errors)
|
49
172
|
rescue JSONAPI::Exceptions::Error => e
|
50
|
-
return JSONAPI::
|
173
|
+
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
51
174
|
end
|
52
175
|
end
|
53
176
|
|
54
177
|
class ReplaceFieldsOperation < Operation
|
55
|
-
attr_reader :
|
178
|
+
attr_reader :data, :resource_id
|
56
179
|
|
57
|
-
def initialize(resource_klass,
|
58
|
-
@resource_id = resource_id
|
59
|
-
@
|
60
|
-
super(resource_klass)
|
180
|
+
def initialize(resource_klass, options = {})
|
181
|
+
@resource_id = options.fetch(:resource_id)
|
182
|
+
@data = options.fetch(:data)
|
183
|
+
super(resource_klass, options)
|
61
184
|
end
|
62
185
|
|
63
186
|
def apply(context)
|
64
187
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
65
|
-
resource.replace_fields(
|
188
|
+
result = resource.replace_fields(data)
|
66
189
|
|
67
|
-
return JSONAPI::
|
190
|
+
return JSONAPI::ResourceOperationResult.new(result == :completed ? :ok : :accepted, resource)
|
68
191
|
end
|
69
192
|
end
|
70
193
|
|
71
194
|
class ReplaceHasOneAssociationOperation < Operation
|
72
195
|
attr_reader :resource_id, :association_type, :key_value
|
73
196
|
|
74
|
-
def initialize(resource_klass,
|
75
|
-
@resource_id = resource_id
|
76
|
-
@key_value = key_value
|
77
|
-
@association_type = association_type.to_sym
|
78
|
-
super(resource_klass)
|
197
|
+
def initialize(resource_klass, options = {})
|
198
|
+
@resource_id = options.fetch(:resource_id)
|
199
|
+
@key_value = options.fetch(:key_value)
|
200
|
+
@association_type = options.fetch(:association_type).to_sym
|
201
|
+
super(resource_klass, options)
|
79
202
|
end
|
80
203
|
|
81
204
|
def apply(context)
|
82
205
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
83
|
-
resource.replace_has_one_link(@association_type, @key_value)
|
206
|
+
result = resource.replace_has_one_link(@association_type, @key_value)
|
84
207
|
|
85
|
-
return JSONAPI::OperationResult.new(:no_content)
|
208
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
86
209
|
end
|
87
210
|
end
|
88
211
|
|
89
212
|
class CreateHasManyAssociationOperation < Operation
|
90
|
-
attr_reader :resource_id, :association_type, :
|
213
|
+
attr_reader :resource_id, :association_type, :data
|
91
214
|
|
92
|
-
def initialize(resource_klass,
|
93
|
-
@resource_id = resource_id
|
94
|
-
@
|
95
|
-
@association_type = association_type.to_sym
|
96
|
-
super(resource_klass)
|
215
|
+
def initialize(resource_klass, options)
|
216
|
+
@resource_id = options.fetch(:resource_id)
|
217
|
+
@data = options.fetch(:data)
|
218
|
+
@association_type = options.fetch(:association_type).to_sym
|
219
|
+
super(resource_klass, options)
|
97
220
|
end
|
98
221
|
|
99
222
|
def apply(context)
|
100
223
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
101
|
-
resource.create_has_many_links(@association_type, @
|
224
|
+
result = resource.create_has_many_links(@association_type, @data)
|
102
225
|
|
103
|
-
return JSONAPI::OperationResult.new(:no_content)
|
226
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
104
227
|
end
|
105
228
|
end
|
106
229
|
|
107
230
|
class ReplaceHasManyAssociationOperation < Operation
|
108
|
-
attr_reader :resource_id, :association_type, :
|
231
|
+
attr_reader :resource_id, :association_type, :data
|
109
232
|
|
110
|
-
def initialize(resource_klass,
|
111
|
-
@resource_id = resource_id
|
112
|
-
@
|
113
|
-
@association_type = association_type.to_sym
|
114
|
-
super(resource_klass)
|
233
|
+
def initialize(resource_klass, options)
|
234
|
+
@resource_id = options.fetch(:resource_id)
|
235
|
+
@data = options.fetch(:data)
|
236
|
+
@association_type = options.fetch(:association_type).to_sym
|
237
|
+
super(resource_klass, options)
|
115
238
|
end
|
116
239
|
|
117
240
|
def apply(context)
|
118
241
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
119
|
-
resource.replace_has_many_links(@association_type, @
|
242
|
+
result = resource.replace_has_many_links(@association_type, @data)
|
120
243
|
|
121
|
-
return JSONAPI::OperationResult.new(:no_content)
|
244
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
122
245
|
end
|
123
246
|
end
|
124
247
|
|
125
248
|
class RemoveHasManyAssociationOperation < Operation
|
126
249
|
attr_reader :resource_id, :association_type, :associated_key
|
127
250
|
|
128
|
-
def initialize(resource_klass,
|
129
|
-
@resource_id = resource_id
|
130
|
-
@associated_key = associated_key
|
131
|
-
@association_type = association_type.to_sym
|
132
|
-
super(resource_klass)
|
251
|
+
def initialize(resource_klass, options)
|
252
|
+
@resource_id = options.fetch(:resource_id)
|
253
|
+
@associated_key = options.fetch(:associated_key)
|
254
|
+
@association_type = options.fetch(:association_type).to_sym
|
255
|
+
super(resource_klass, options)
|
133
256
|
end
|
134
257
|
|
135
258
|
def apply(context)
|
136
259
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
137
|
-
resource.remove_has_many_link(@association_type, @associated_key)
|
138
|
-
|
139
|
-
return JSONAPI::OperationResult.new(:no_content)
|
260
|
+
result = resource.remove_has_many_link(@association_type, @associated_key)
|
140
261
|
|
141
|
-
|
142
|
-
raise JSONAPI::Exceptions::RecordNotFound.new(@associated_key)
|
262
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
143
263
|
end
|
144
264
|
end
|
145
265
|
|
146
266
|
class RemoveHasOneAssociationOperation < Operation
|
147
267
|
attr_reader :resource_id, :association_type
|
148
268
|
|
149
|
-
def initialize(resource_klass,
|
150
|
-
@resource_id = resource_id
|
151
|
-
@association_type = association_type.to_sym
|
152
|
-
super(resource_klass)
|
269
|
+
def initialize(resource_klass, options)
|
270
|
+
@resource_id = options.fetch(:resource_id)
|
271
|
+
@association_type = options.fetch(:association_type).to_sym
|
272
|
+
super(resource_klass, options)
|
153
273
|
end
|
154
274
|
|
155
275
|
def apply(context)
|
156
276
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
157
|
-
resource.remove_has_one_link(@association_type)
|
277
|
+
result = resource.remove_has_one_link(@association_type)
|
158
278
|
|
159
|
-
return JSONAPI::OperationResult.new(:no_content)
|
279
|
+
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
160
280
|
end
|
161
281
|
end
|
162
282
|
end
|
@@ -1,15 +1,48 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
class OperationResult
|
3
|
-
attr_accessor :code
|
3
|
+
attr_accessor :code
|
4
|
+
attr_accessor :meta
|
4
5
|
|
5
|
-
def initialize(code
|
6
|
+
def initialize(code)
|
6
7
|
@code = code
|
7
|
-
@
|
8
|
+
@meta = {}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ErrorsOperationResult < OperationResult
|
13
|
+
attr_accessor :errors
|
14
|
+
|
15
|
+
def initialize(code, errors)
|
8
16
|
@errors = errors
|
17
|
+
super(code)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ResourceOperationResult < OperationResult
|
22
|
+
attr_accessor :resource
|
23
|
+
|
24
|
+
def initialize(code, resource)
|
25
|
+
@resource = resource
|
26
|
+
super(code)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ResourcesOperationResult < OperationResult
|
31
|
+
attr_accessor :resources
|
32
|
+
|
33
|
+
def initialize(code, resources)
|
34
|
+
@resources = resources
|
35
|
+
super(code)
|
9
36
|
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class LinksObjectOperationResult < OperationResult
|
40
|
+
attr_accessor :parent_resource, :association
|
10
41
|
|
11
|
-
def
|
12
|
-
|
42
|
+
def initialize(code, parent_resource, association)
|
43
|
+
@parent_resource = parent_resource
|
44
|
+
@association = association
|
45
|
+
super(code)
|
13
46
|
end
|
14
47
|
end
|
15
48
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module JSONAPI
|
2
|
+
class OperationResults
|
3
|
+
attr_accessor :results
|
4
|
+
attr_accessor :meta
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@results = []
|
8
|
+
@has_errors = false
|
9
|
+
@meta = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_result(result)
|
13
|
+
@has_errors = true if result.is_a?(JSONAPI::ErrorsOperationResult)
|
14
|
+
@results.push(result)
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_errors?
|
18
|
+
@has_errors
|
19
|
+
end
|
20
|
+
|
21
|
+
def all_errors
|
22
|
+
errors = []
|
23
|
+
if @has_errors
|
24
|
+
@results.each do |result|
|
25
|
+
if result.is_a?(JSONAPI::ErrorsOperationResult)
|
26
|
+
errors.concat(result.errors)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
errors
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,30 +1,63 @@
|
|
1
|
-
require 'jsonapi/operation_result'
|
2
|
-
require 'jsonapi/callbacks'
|
3
|
-
|
4
1
|
module JSONAPI
|
5
2
|
class OperationsProcessor
|
6
3
|
include Callbacks
|
7
|
-
define_jsonapi_resources_callbacks :operation,
|
4
|
+
define_jsonapi_resources_callbacks :operation,
|
5
|
+
:operations,
|
6
|
+
:find_operation,
|
7
|
+
:show_operation,
|
8
|
+
:show_association_operation,
|
9
|
+
:show_related_resource_operation,
|
10
|
+
:show_related_resources_operation,
|
11
|
+
:create_resource_operation,
|
12
|
+
:remove_resource_operation,
|
13
|
+
:replace_fields_operation,
|
14
|
+
:replace_has_one_association_operation,
|
15
|
+
:create_has_many_association_operation,
|
16
|
+
:replace_has_many_association_operation,
|
17
|
+
:remove_has_many_association_operation,
|
18
|
+
:remove_has_one_association_operation
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def operations_processor_for(operations_processor)
|
22
|
+
operations_processor_class_name = "#{operations_processor.to_s.camelize}OperationsProcessor"
|
23
|
+
operations_processor_class_name.safe_constantize
|
24
|
+
end
|
25
|
+
end
|
8
26
|
|
9
27
|
def process(request)
|
10
|
-
@results =
|
28
|
+
@results = JSONAPI::OperationResults.new
|
11
29
|
@request = request
|
12
30
|
@context = request.context
|
13
31
|
@operations = request.operations
|
14
32
|
|
33
|
+
# Use transactions if more than one operation and if one of the operations can be transactional
|
34
|
+
# Even if transactional transactions won't be used unless the derived OperationsProcessor supports them.
|
35
|
+
@transactional = false
|
36
|
+
if @operations.length > 1
|
37
|
+
@operations.each do |operation|
|
38
|
+
@transactional = @transactional | operation.transactional
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
15
42
|
run_callbacks :operations do
|
16
43
|
transaction do
|
44
|
+
@operations_meta = {}
|
17
45
|
@operations.each do |operation|
|
18
46
|
@operation = operation
|
19
|
-
@
|
47
|
+
@operation_meta = {}
|
20
48
|
run_callbacks :operation do
|
21
|
-
@result =
|
22
|
-
@
|
23
|
-
|
49
|
+
@result = nil
|
50
|
+
run_callbacks @operation.class.name.demodulize.underscore.to_sym do
|
51
|
+
@result = process_operation(@operation)
|
52
|
+
end
|
53
|
+
@result.meta.merge!(@operation_meta)
|
54
|
+
@results.add_result(@result)
|
55
|
+
if @results.has_errors?
|
24
56
|
rollback
|
25
57
|
end
|
26
58
|
end
|
27
59
|
end
|
60
|
+
@results.meta = @operations_meta
|
28
61
|
end
|
29
62
|
end
|
30
63
|
@results
|
@@ -41,5 +74,12 @@ module JSONAPI
|
|
41
74
|
|
42
75
|
def rollback
|
43
76
|
end
|
77
|
+
|
78
|
+
def process_operation(operation)
|
79
|
+
operation.apply(@context)
|
80
|
+
end
|
44
81
|
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class BasicOperationsProcessor < JSONAPI::OperationsProcessor
|
45
85
|
end
|