jsonapi-resources 0.8.3 → 0.9.0.beta1
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 +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
|