jsonapi-resources 0.8.3 → 0.9.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2124 -8
- data/lib/jsonapi-resources.rb +2 -0
- data/lib/jsonapi/acts_as_resource_controller.rb +70 -29
- data/lib/jsonapi/cached_resource_fragment.rb +119 -0
- data/lib/jsonapi/compiled_json.rb +36 -0
- data/lib/jsonapi/configuration.rb +54 -4
- data/lib/jsonapi/error_codes.rb +2 -2
- data/lib/jsonapi/exceptions.rb +19 -13
- data/lib/jsonapi/formatter.rb +15 -1
- data/lib/jsonapi/include_directives.rb +23 -3
- data/lib/jsonapi/processor.rb +69 -27
- data/lib/jsonapi/relationship_builder.rb +23 -21
- data/lib/jsonapi/request_parser.rb +27 -72
- data/lib/jsonapi/resource.rb +234 -38
- data/lib/jsonapi/resource_serializer.rb +229 -95
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +9 -20
- metadata +25 -9
data/lib/jsonapi/error_codes.rb
CHANGED
@@ -7,7 +7,6 @@ module JSONAPI
|
|
7
7
|
PARAM_NOT_ALLOWED = '105'
|
8
8
|
PARAM_MISSING = '106'
|
9
9
|
INVALID_FILTER_VALUE = '107'
|
10
|
-
COUNT_MISMATCH = '108'
|
11
10
|
KEY_ORDER_MISMATCH = '109'
|
12
11
|
KEY_NOT_INCLUDED_IN_URL = '110'
|
13
12
|
INVALID_INCLUDE = '112'
|
@@ -20,6 +19,7 @@ module JSONAPI
|
|
20
19
|
INVALID_FIELD_FORMAT = '119'
|
21
20
|
INVALID_FILTERS_SYNTAX = '120'
|
22
21
|
SAVE_FAILED = '121'
|
22
|
+
INVALID_DATA_FORMAT = '122'
|
23
23
|
FORBIDDEN = '403'
|
24
24
|
RECORD_NOT_FOUND = '404'
|
25
25
|
NOT_ACCEPTABLE = '406'
|
@@ -36,7 +36,6 @@ module JSONAPI
|
|
36
36
|
PARAM_NOT_ALLOWED => 'PARAM_NOT_ALLOWED',
|
37
37
|
PARAM_MISSING => 'PARAM_MISSING',
|
38
38
|
INVALID_FILTER_VALUE => 'INVALID_FILTER_VALUE',
|
39
|
-
COUNT_MISMATCH => 'COUNT_MISMATCH',
|
40
39
|
KEY_ORDER_MISMATCH => 'KEY_ORDER_MISMATCH',
|
41
40
|
KEY_NOT_INCLUDED_IN_URL => 'KEY_NOT_INCLUDED_IN_URL',
|
42
41
|
INVALID_INCLUDE => 'INVALID_INCLUDE',
|
@@ -49,6 +48,7 @@ module JSONAPI
|
|
49
48
|
INVALID_FIELD_FORMAT => 'INVALID_FIELD_FORMAT',
|
50
49
|
INVALID_FILTERS_SYNTAX => 'INVALID_FILTERS_SYNTAX',
|
51
50
|
SAVE_FAILED => 'SAVE_FAILED',
|
51
|
+
INVALID_DATA_FORMAT => 'INVALID_DATA_FORMAT',
|
52
52
|
FORBIDDEN => 'FORBIDDEN',
|
53
53
|
RECORD_NOT_FOUND => 'RECORD_NOT_FOUND',
|
54
54
|
NOT_ACCEPTABLE => 'NOT_ACCEPTABLE',
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
module Exceptions
|
3
|
-
class Error < RuntimeError
|
3
|
+
class Error < RuntimeError
|
4
|
+
def errors
|
5
|
+
# :nocov:
|
6
|
+
raise NotImplementedError, "Subclass of Error must implement errors method"
|
7
|
+
# :nocov:
|
8
|
+
end
|
9
|
+
end
|
4
10
|
|
5
11
|
class InternalServerError < Error
|
6
12
|
attr_accessor :exception
|
@@ -10,7 +16,7 @@ module JSONAPI
|
|
10
16
|
end
|
11
17
|
|
12
18
|
def errors
|
13
|
-
|
19
|
+
if JSONAPI.configuration.include_backtraces_in_errors
|
14
20
|
meta = Hash.new
|
15
21
|
meta[:exception] = exception.message
|
16
22
|
meta[:backtrace] = exception.backtrace
|
@@ -204,6 +210,17 @@ module JSONAPI
|
|
204
210
|
end
|
205
211
|
end
|
206
212
|
|
213
|
+
class InvalidDataFormat < Error
|
214
|
+
def errors
|
215
|
+
[JSONAPI::Error.new(code: JSONAPI::INVALID_DATA_FORMAT,
|
216
|
+
status: :bad_request,
|
217
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_data_format.title',
|
218
|
+
default: 'Invalid data format'),
|
219
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_data_format.detail',
|
220
|
+
default: 'Data must be a hash.'))]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
207
224
|
class InvalidLinksObject < Error
|
208
225
|
def errors
|
209
226
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_LINKS_OBJECT,
|
@@ -320,17 +337,6 @@ module JSONAPI
|
|
320
337
|
end
|
321
338
|
end
|
322
339
|
|
323
|
-
class CountMismatch < Error
|
324
|
-
def errors
|
325
|
-
[JSONAPI::Error.new(code: JSONAPI::COUNT_MISMATCH,
|
326
|
-
status: :bad_request,
|
327
|
-
title: I18n.translate('jsonapi-resources.exceptions.count_mismatch.title',
|
328
|
-
default: 'Count to key mismatch'),
|
329
|
-
detail: I18n.translate('jsonapi-resources.exceptions.count_mismatch.detail',
|
330
|
-
default: 'The resource collection does not contain the same number of objects as the number of keys.'))]
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
340
|
class KeyNotIncludedInURL < Error
|
335
341
|
attr_accessor :key
|
336
342
|
def initialize(key)
|
data/lib/jsonapi/formatter.rb
CHANGED
@@ -13,6 +13,10 @@ module JSONAPI
|
|
13
13
|
return FormatterWrapperCache.new(self)
|
14
14
|
end
|
15
15
|
|
16
|
+
def uncached
|
17
|
+
return self
|
18
|
+
end
|
19
|
+
|
16
20
|
def formatter_for(format)
|
17
21
|
"#{format.to_s.camelize}Formatter".safe_constantize
|
18
22
|
end
|
@@ -80,6 +84,10 @@ module JSONAPI
|
|
80
84
|
def cached
|
81
85
|
self
|
82
86
|
end
|
87
|
+
|
88
|
+
def uncached
|
89
|
+
return @formatter_klass
|
90
|
+
end
|
83
91
|
end
|
84
92
|
end
|
85
93
|
|
@@ -113,7 +121,13 @@ end
|
|
113
121
|
class DefaultValueFormatter < JSONAPI::ValueFormatter
|
114
122
|
class << self
|
115
123
|
def format(raw_value)
|
116
|
-
raw_value
|
124
|
+
case raw_value
|
125
|
+
when Date, Time, DateTime, ActiveSupport::TimeWithZone, BigDecimal
|
126
|
+
# Use the as_json methods added to various base classes by ActiveSupport
|
127
|
+
return raw_value.as_json
|
128
|
+
else
|
129
|
+
return raw_value
|
130
|
+
end
|
117
131
|
end
|
118
132
|
end
|
119
133
|
end
|
@@ -36,6 +36,10 @@ module JSONAPI
|
|
36
36
|
get_includes(@include_directives_hash)
|
37
37
|
end
|
38
38
|
|
39
|
+
def paths
|
40
|
+
delve_paths(get_includes(@include_directives_hash, false))
|
41
|
+
end
|
42
|
+
|
39
43
|
private
|
40
44
|
|
41
45
|
def get_related(current_path)
|
@@ -59,9 +63,12 @@ module JSONAPI
|
|
59
63
|
current
|
60
64
|
end
|
61
65
|
|
62
|
-
def get_includes(directive)
|
63
|
-
directive[:include_related]
|
64
|
-
|
66
|
+
def get_includes(directive, only_joined_includes = true)
|
67
|
+
ir = directive[:include_related]
|
68
|
+
ir = ir.select { |k,v| v[:include_in_join] } if only_joined_includes
|
69
|
+
|
70
|
+
ir.map do |name, sub_directive|
|
71
|
+
sub = get_includes(sub_directive, only_joined_includes)
|
65
72
|
sub.any? ? { name => sub } : name
|
66
73
|
end
|
67
74
|
end
|
@@ -76,5 +83,18 @@ module JSONAPI
|
|
76
83
|
related[:include] = true
|
77
84
|
end
|
78
85
|
end
|
86
|
+
|
87
|
+
def delve_paths(obj)
|
88
|
+
case obj
|
89
|
+
when Array
|
90
|
+
obj.map{|elem| delve_paths(elem)}.flatten(1)
|
91
|
+
when Hash
|
92
|
+
obj.map{|k,v| [[k]] + delve_paths(v).map{|path| [k] + path } }.flatten(1)
|
93
|
+
when Symbol, String
|
94
|
+
[[obj]]
|
95
|
+
else
|
96
|
+
raise "delve_paths cannot descend into #{obj.class.name}"
|
97
|
+
end
|
98
|
+
end
|
79
99
|
end
|
80
100
|
end
|
data/lib/jsonapi/processor.rb
CHANGED
@@ -11,9 +11,9 @@ module JSONAPI
|
|
11
11
|
:replace_fields,
|
12
12
|
:replace_to_one_relationship,
|
13
13
|
:replace_polymorphic_to_one_relationship,
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
14
|
+
:create_to_many_relationships,
|
15
|
+
:replace_to_many_relationships,
|
16
|
+
:remove_to_many_relationships,
|
17
17
|
:remove_to_one_relationship,
|
18
18
|
:operation
|
19
19
|
|
@@ -71,12 +71,21 @@ module JSONAPI
|
|
71
71
|
fields = params[:fields]
|
72
72
|
|
73
73
|
verified_filters = resource_klass.verify_filters(filters, context)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
find_options = {
|
75
|
+
context: context,
|
76
|
+
include_directives: include_directives,
|
77
|
+
sort_criteria: sort_criteria,
|
78
|
+
paginator: paginator,
|
79
|
+
fields: fields
|
80
|
+
}
|
81
|
+
|
82
|
+
resource_records = if params[:cache_serializer]
|
83
|
+
resource_klass.find_serialized_with_caching(verified_filters,
|
84
|
+
params[:cache_serializer],
|
85
|
+
find_options)
|
86
|
+
else
|
87
|
+
resource_klass.find(verified_filters, find_options)
|
88
|
+
end
|
80
89
|
|
81
90
|
page_options = {}
|
82
91
|
if (JSONAPI.configuration.top_level_meta_include_record_count ||
|
@@ -104,10 +113,19 @@ module JSONAPI
|
|
104
113
|
|
105
114
|
key = resource_klass.verify_key(id, context)
|
106
115
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
116
|
+
find_options = {
|
117
|
+
context: context,
|
118
|
+
include_directives: include_directives,
|
119
|
+
fields: fields
|
120
|
+
}
|
121
|
+
|
122
|
+
resource_record = if params[:cache_serializer]
|
123
|
+
resource_klass.find_by_key_serialized_with_caching(key,
|
124
|
+
params[:cache_serializer],
|
125
|
+
find_options)
|
126
|
+
else
|
127
|
+
resource_klass.find_by_key(key, find_options)
|
128
|
+
end
|
111
129
|
|
112
130
|
return JSONAPI::ResourceOperationResult.new(:ok, resource_record)
|
113
131
|
end
|
@@ -129,6 +147,7 @@ module JSONAPI
|
|
129
147
|
relationship_type = params[:relationship_type].to_sym
|
130
148
|
fields = params[:fields]
|
131
149
|
|
150
|
+
# TODO Should fetch related_resource from cache if caching enabled
|
132
151
|
source_resource = source_klass.find_by_key(source_id, context: context, fields: fields)
|
133
152
|
|
134
153
|
related_resource = source_resource.public_send(relationship_type)
|
@@ -141,20 +160,37 @@ module JSONAPI
|
|
141
160
|
source_id = params[:source_id]
|
142
161
|
relationship_type = params[:relationship_type]
|
143
162
|
filters = params[:filters]
|
144
|
-
include_directives = params[:include_directives]
|
145
163
|
sort_criteria = params[:sort_criteria]
|
146
164
|
paginator = params[:paginator]
|
147
165
|
fields = params[:fields]
|
166
|
+
include_directives = params[:include_directives]
|
148
167
|
|
149
168
|
source_resource ||= source_klass.find_by_key(source_id, context: context, fields: fields)
|
150
169
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
170
|
+
rel_opts = {
|
171
|
+
filters: filters,
|
172
|
+
sort_criteria: sort_criteria,
|
173
|
+
paginator: paginator,
|
174
|
+
fields: fields,
|
175
|
+
context: context,
|
176
|
+
include_directives: include_directives
|
177
|
+
}
|
178
|
+
|
179
|
+
related_resources = nil
|
180
|
+
if params[:cache_serializer]
|
181
|
+
# TODO Could also avoid instantiating source_resource as actual Resource by
|
182
|
+
# allowing LinkBuilder to accept CachedResourceFragment as source in
|
183
|
+
# relationships_related_link
|
184
|
+
scope = source_resource.public_send(:"records_for_#{relationship_type}", rel_opts)
|
185
|
+
relationship = source_klass._relationship(relationship_type)
|
186
|
+
related_resources = relationship.resource_klass.find_serialized_with_caching(
|
187
|
+
scope,
|
188
|
+
params[:cache_serializer],
|
189
|
+
rel_opts
|
190
|
+
)
|
191
|
+
else
|
192
|
+
related_resources = source_resource.public_send(relationship_type, rel_opts)
|
193
|
+
end
|
158
194
|
|
159
195
|
if ((JSONAPI.configuration.top_level_meta_include_record_count) ||
|
160
196
|
(paginator && paginator.class.requires_record_count) ||
|
@@ -240,7 +276,7 @@ module JSONAPI
|
|
240
276
|
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
241
277
|
end
|
242
278
|
|
243
|
-
def
|
279
|
+
def create_to_many_relationships
|
244
280
|
resource_id = params[:resource_id]
|
245
281
|
relationship_type = params[:relationship_type].to_sym
|
246
282
|
data = params[:data]
|
@@ -251,7 +287,7 @@ module JSONAPI
|
|
251
287
|
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
252
288
|
end
|
253
289
|
|
254
|
-
def
|
290
|
+
def replace_to_many_relationships
|
255
291
|
resource_id = params[:resource_id]
|
256
292
|
relationship_type = params[:relationship_type].to_sym
|
257
293
|
data = params.fetch(:data)
|
@@ -262,15 +298,21 @@ module JSONAPI
|
|
262
298
|
return JSONAPI::OperationResult.new(result == :completed ? :no_content : :accepted)
|
263
299
|
end
|
264
300
|
|
265
|
-
def
|
301
|
+
def remove_to_many_relationships
|
266
302
|
resource_id = params[:resource_id]
|
267
303
|
relationship_type = params[:relationship_type].to_sym
|
268
|
-
|
304
|
+
associated_keys = params[:associated_keys]
|
269
305
|
|
270
306
|
resource = resource_klass.find_by_key(resource_id, context: context)
|
271
|
-
result = resource.remove_to_many_link(relationship_type, associated_key)
|
272
307
|
|
273
|
-
|
308
|
+
complete = true
|
309
|
+
associated_keys.each do |key|
|
310
|
+
result = resource.remove_to_many_link(relationship_type, key)
|
311
|
+
if complete && result != :completed
|
312
|
+
complete = false
|
313
|
+
end
|
314
|
+
end
|
315
|
+
return JSONAPI::OperationResult.new(complete ? :no_content : :accepted)
|
274
316
|
end
|
275
317
|
|
276
318
|
def remove_to_one_relationship
|
@@ -53,10 +53,30 @@ module JSONAPI
|
|
53
53
|
}
|
54
54
|
.fetch(type)
|
55
55
|
|
56
|
-
define_on_resource associated_records_method_name do
|
56
|
+
define_on_resource associated_records_method_name do |options = {}|
|
57
57
|
relationship = self.class._relationships[relationship_name]
|
58
58
|
relation_name = relationship.relation_name(context: @context)
|
59
|
-
records_for(relation_name)
|
59
|
+
records = records_for(relation_name)
|
60
|
+
|
61
|
+
resource_klass = relationship.resource_klass
|
62
|
+
|
63
|
+
filters = options.fetch(:filters, {})
|
64
|
+
unless filters.nil? || filters.empty?
|
65
|
+
records = resource_klass.apply_filters(records, filters, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
sort_criteria = options.fetch(:sort_criteria, {})
|
69
|
+
unless sort_criteria.nil? || sort_criteria.empty?
|
70
|
+
order_options = relationship.resource_klass.construct_order_options(sort_criteria)
|
71
|
+
records = resource_klass.apply_sort(records, order_options, @context)
|
72
|
+
end
|
73
|
+
|
74
|
+
paginator = options[:paginator]
|
75
|
+
if paginator
|
76
|
+
records = resource_klass.apply_pagination(records, paginator, order_options)
|
77
|
+
end
|
78
|
+
|
79
|
+
records
|
60
80
|
end
|
61
81
|
|
62
82
|
associated_records_method_name
|
@@ -122,25 +142,7 @@ module JSONAPI
|
|
122
142
|
relationship = self.class._relationships[relationship_name]
|
123
143
|
|
124
144
|
resource_klass = relationship.resource_klass
|
125
|
-
records = public_send(associated_records_method_name)
|
126
|
-
|
127
|
-
filters = options.fetch(:filters, {})
|
128
|
-
unless filters.nil? || filters.empty?
|
129
|
-
records = resource_klass.apply_filters(records, filters, options)
|
130
|
-
end
|
131
|
-
|
132
|
-
records = resource_klass.apply_includes(records, options)
|
133
|
-
|
134
|
-
sort_criteria = options.fetch(:sort_criteria, {})
|
135
|
-
unless sort_criteria.nil? || sort_criteria.empty?
|
136
|
-
order_options = relationship.resource_klass.construct_order_options(sort_criteria)
|
137
|
-
records = resource_klass.apply_sort(records, order_options, @context)
|
138
|
-
end
|
139
|
-
|
140
|
-
paginator = options[:paginator]
|
141
|
-
if paginator
|
142
|
-
records = resource_klass.apply_pagination(records, paginator, order_options)
|
143
|
-
end
|
145
|
+
records = public_send(associated_records_method_name, options)
|
144
146
|
|
145
147
|
return records.collect do |record|
|
146
148
|
if relationship.polymorphic?
|
@@ -122,7 +122,7 @@ module JSONAPI
|
|
122
122
|
if data_required
|
123
123
|
data = params.fetch(:data)
|
124
124
|
object_params = { relationships: { format_key(relationship.name) => { data: data } } }
|
125
|
-
verified_params = parse_params(object_params, updatable_fields)
|
125
|
+
verified_params = parse_params(object_params, @resource_klass.updatable_fields(@context))
|
126
126
|
|
127
127
|
parse_arguments = [verified_params, relationship, parent_key]
|
128
128
|
else
|
@@ -201,7 +201,7 @@ module JSONAPI
|
|
201
201
|
relationship = resource_klass._relationship(relationship_name)
|
202
202
|
if relationship && format_key(relationship_name) == include_parts.first
|
203
203
|
unless include_parts.last.empty?
|
204
|
-
check_include(Resource.resource_for(resource_klass.module_path + relationship.class_name.to_s.underscore), include_parts.last.partition('.'))
|
204
|
+
check_include(Resource.resource_for(@resource_klass.module_path + relationship.class_name.to_s.underscore), include_parts.last.partition('.'))
|
205
205
|
end
|
206
206
|
else
|
207
207
|
@errors.concat(JSONAPI::Exceptions::InvalidInclude.new(format_key(resource_klass._type),
|
@@ -346,30 +346,19 @@ module JSONAPI
|
|
346
346
|
)
|
347
347
|
end
|
348
348
|
|
349
|
-
|
350
|
-
|
351
|
-
def creatable_fields
|
352
|
-
if @resource_klass.respond_to?(:createable_fields)
|
353
|
-
creatable_fields = @resource_klass.createable_fields(@context)
|
354
|
-
else
|
355
|
-
creatable_fields = @resource_klass.creatable_fields(@context)
|
356
|
-
end
|
357
|
-
end
|
358
|
-
# :nocov:
|
349
|
+
def parse_add_operation(params)
|
350
|
+
fail JSONAPI::Exceptions::InvalidDataFormat unless params.respond_to?(:each_pair)
|
359
351
|
|
360
|
-
|
361
|
-
Array.wrap(data).each do |params|
|
362
|
-
verify_type(params[:type])
|
352
|
+
verify_type(params[:type])
|
363
353
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
end
|
354
|
+
data = parse_params(params, @resource_klass.creatable_fields(@context))
|
355
|
+
@operations.push JSONAPI::Operation.new(:create_resource,
|
356
|
+
@resource_klass,
|
357
|
+
context: @context,
|
358
|
+
data: data,
|
359
|
+
fields: @fields,
|
360
|
+
include_directives: @include_directives
|
361
|
+
)
|
373
362
|
rescue JSONAPI::Exceptions::Error => e
|
374
363
|
@errors.concat(e.errors)
|
375
364
|
end
|
@@ -567,20 +556,9 @@ module JSONAPI
|
|
567
556
|
end
|
568
557
|
end
|
569
558
|
|
570
|
-
# TODO: Please remove after `updateable_fields` is removed
|
571
|
-
# :nocov:
|
572
|
-
def updatable_fields
|
573
|
-
if @resource_klass.respond_to?(:updateable_fields)
|
574
|
-
@resource_klass.updateable_fields(@context)
|
575
|
-
else
|
576
|
-
@resource_klass.updatable_fields(@context)
|
577
|
-
end
|
578
|
-
end
|
579
|
-
# :nocov:
|
580
|
-
|
581
559
|
def parse_add_relationship_operation(verified_params, relationship, parent_key)
|
582
560
|
if relationship.is_a?(JSONAPI::Relationship::ToMany)
|
583
|
-
@operations.push JSONAPI::Operation.new(:
|
561
|
+
@operations.push JSONAPI::Operation.new(:create_to_many_relationships,
|
584
562
|
resource_klass,
|
585
563
|
context: @context,
|
586
564
|
resource_id: parent_key,
|
@@ -612,13 +590,15 @@ module JSONAPI
|
|
612
590
|
fail JSONAPI::Exceptions::ToManySetReplacementForbidden.new
|
613
591
|
end
|
614
592
|
options[:data] = verified_params[:to_many].values[0]
|
615
|
-
operation_type = :
|
593
|
+
operation_type = :replace_to_many_relationships
|
616
594
|
end
|
617
595
|
|
618
596
|
@operations.push JSONAPI::Operation.new(operation_type, resource_klass, options)
|
619
597
|
end
|
620
598
|
|
621
599
|
def parse_single_replace_operation(data, keys, id_key_presence_check_required: true)
|
600
|
+
fail JSONAPI::Exceptions::InvalidDataFormat unless data.respond_to?(:each_pair)
|
601
|
+
|
622
602
|
fail JSONAPI::Exceptions::MissingKey.new if data[:id].nil?
|
623
603
|
|
624
604
|
key = data[:id].to_s
|
@@ -634,38 +614,23 @@ module JSONAPI
|
|
634
614
|
@resource_klass,
|
635
615
|
context: @context,
|
636
616
|
resource_id: key,
|
637
|
-
data: parse_params(data, updatable_fields),
|
617
|
+
data: parse_params(data, @resource_klass.updatable_fields(@context)),
|
638
618
|
fields: @fields,
|
639
619
|
include_directives: @include_directives
|
640
620
|
)
|
641
621
|
end
|
642
622
|
|
643
623
|
def parse_replace_operation(data, keys)
|
644
|
-
|
645
|
-
fail JSONAPI::Exceptions::CountMismatch if keys.count != data.count
|
646
|
-
|
647
|
-
data.each do |object_params|
|
648
|
-
parse_single_replace_operation(object_params, keys)
|
649
|
-
end
|
650
|
-
else
|
651
|
-
parse_single_replace_operation(data, [keys],
|
652
|
-
id_key_presence_check_required: keys.present?)
|
653
|
-
end
|
654
|
-
|
624
|
+
parse_single_replace_operation(data, [keys], id_key_presence_check_required: keys.present?)
|
655
625
|
rescue JSONAPI::Exceptions::Error => e
|
656
626
|
@errors.concat(e.errors)
|
657
627
|
end
|
658
628
|
|
659
629
|
def parse_remove_operation(params)
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
@
|
664
|
-
@resource_klass,
|
665
|
-
context: @context,
|
666
|
-
resource_id: key
|
667
|
-
)
|
668
|
-
end
|
630
|
+
@operations.push JSONAPI::Operation.new(:remove_resource,
|
631
|
+
@resource_klass,
|
632
|
+
context: @context,
|
633
|
+
resource_id: @resource_klass.verify_key(params.require(:id), context))
|
669
634
|
rescue JSONAPI::Exceptions::Error => e
|
670
635
|
@errors.concat(e.errors)
|
671
636
|
end
|
@@ -678,25 +643,15 @@ module JSONAPI
|
|
678
643
|
)
|
679
644
|
|
680
645
|
if relationship.is_a?(JSONAPI::Relationship::ToMany)
|
646
|
+
operation_args = operation_base_args.dup
|
681
647
|
keys = params[:to_many].values[0]
|
682
|
-
|
683
|
-
|
684
|
-
operation_args[1] = operation_args[1].merge(associated_key: key)
|
685
|
-
@operations.push JSONAPI::Operation.new(:remove_to_many_relationship,
|
686
|
-
*operation_args
|
687
|
-
)
|
688
|
-
end
|
648
|
+
operation_args[1] = operation_args[1].merge(associated_keys: keys)
|
649
|
+
@operations.push JSONAPI::Operation.new(:remove_to_many_relationships, *operation_args)
|
689
650
|
else
|
690
|
-
@operations.push JSONAPI::Operation.new(:remove_to_one_relationship,
|
691
|
-
*operation_base_args
|
692
|
-
)
|
651
|
+
@operations.push JSONAPI::Operation.new(:remove_to_one_relationship, *operation_base_args)
|
693
652
|
end
|
694
653
|
end
|
695
654
|
|
696
|
-
def parse_key_array(raw)
|
697
|
-
@resource_klass.verify_keys(raw.split(/,/), context)
|
698
|
-
end
|
699
|
-
|
700
655
|
def format_key(key)
|
701
656
|
@key_formatter.format(key)
|
702
657
|
end
|