jsonapi-resources 0.7.0 → 0.7.1.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 +196 -190
- data/lib/generators/jsonapi/USAGE +6 -1
- data/lib/generators/jsonapi/controller_generator.rb +14 -0
- data/lib/generators/jsonapi/templates/jsonapi_controller.rb +4 -0
- data/lib/jsonapi/active_record_operations_processor.rb +4 -3
- data/lib/jsonapi/acts_as_resource_controller.rb +7 -3
- data/lib/jsonapi/error_codes.rb +26 -26
- data/lib/jsonapi/exceptions.rb +124 -53
- data/lib/jsonapi/relationship.rb +8 -0
- data/lib/jsonapi/request.rb +4 -6
- data/lib/jsonapi/resource.rb +37 -13
- data/lib/jsonapi/resource_controller.rb +14 -2
- data/lib/jsonapi/resource_serializer.rb +2 -8
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/routing_ext.rb +1 -1
- data/locales/en.yml +80 -0
- data/test/controllers/controller_test.rb +35 -5
- data/test/fixtures/active_record.rb +11 -8
- data/test/fixtures/comments.yml +1 -1
- data/test/fixtures/preferences.yml +0 -4
- data/test/lib/generators/jsonapi/controller_generator_test.rb +25 -0
- data/test/test_helper.rb +3 -0
- data/test/unit/operation/operations_processor_test.rb +3 -3
- data/test/unit/resource/resource_test.rb +20 -0
- data/test/unit/serializer/serializer_test.rb +0 -6
- metadata +10 -5
@@ -1,8 +1,13 @@
|
|
1
1
|
Description:
|
2
2
|
Generator for JSONAPI Resources
|
3
3
|
|
4
|
-
|
4
|
+
Examples:
|
5
5
|
rails generate jsonapi:resource Post
|
6
6
|
|
7
7
|
This will create:
|
8
8
|
app/resources/post_resource.rb
|
9
|
+
|
10
|
+
rails generate jsonapi:controller Post
|
11
|
+
|
12
|
+
This will create:
|
13
|
+
app/controllers/posts_controller.rb
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jsonapi
|
2
|
+
class ControllerGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def create_resource
|
6
|
+
template_file = File.join(
|
7
|
+
'app/controllers',
|
8
|
+
class_path,
|
9
|
+
"#{file_name.pluralize}_controller.rb"
|
10
|
+
)
|
11
|
+
template 'jsonapi_controller.rb', template_file
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -18,7 +18,7 @@ class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
|
|
18
18
|
# Catch errors that should be handled before JSONAPI::Exceptions::Error
|
19
19
|
# and other unprocessed exceptions
|
20
20
|
def process_operation(operation)
|
21
|
-
with_default_handling do
|
21
|
+
with_default_handling do
|
22
22
|
begin
|
23
23
|
operation.apply
|
24
24
|
rescue ActiveRecord::DeleteRestrictionError => e
|
@@ -26,9 +26,10 @@ class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
|
|
26
26
|
return JSONAPI::ErrorsOperationResult.new(record_locked_error.errors[0].code, record_locked_error.errors)
|
27
27
|
|
28
28
|
rescue ActiveRecord::RecordNotFound
|
29
|
-
|
29
|
+
key = operation.respond_to?(:associated_key) ? operation.associated_key : :unavailable
|
30
|
+
record_not_found = JSONAPI::Exceptions::RecordNotFound.new(key)
|
30
31
|
return JSONAPI::ErrorsOperationResult.new(record_not_found.errors[0].code, record_not_found.errors)
|
31
32
|
end
|
32
|
-
end
|
33
|
+
end
|
33
34
|
end
|
34
35
|
end
|
@@ -179,9 +179,13 @@ module JSONAPI
|
|
179
179
|
when JSONAPI::Exceptions::Error
|
180
180
|
render_errors(e.errors)
|
181
181
|
else
|
182
|
-
|
183
|
-
|
184
|
-
|
182
|
+
if JSONAPI.configuration.exception_class_whitelist.any? { |k| e.class.ancestors.include?(k) }
|
183
|
+
fail e
|
184
|
+
else
|
185
|
+
internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
|
186
|
+
Rails.logger.error { "Internal Server Error: #{e.message} #{e.backtrace.join("\n")}" }
|
187
|
+
render_errors(internal_server_error.errors)
|
188
|
+
end
|
185
189
|
end
|
186
190
|
end
|
187
191
|
|
data/lib/jsonapi/error_codes.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
module JSONAPI
|
2
|
-
VALIDATION_ERROR = 100
|
3
|
-
INVALID_RESOURCE = 101
|
4
|
-
FILTER_NOT_ALLOWED = 102
|
5
|
-
INVALID_FIELD_VALUE = 103
|
6
|
-
INVALID_FIELD = 104
|
7
|
-
PARAM_NOT_ALLOWED = 105
|
8
|
-
PARAM_MISSING = 106
|
9
|
-
INVALID_FILTER_VALUE = 107
|
10
|
-
COUNT_MISMATCH = 108
|
11
|
-
KEY_ORDER_MISMATCH = 109
|
12
|
-
KEY_NOT_INCLUDED_IN_URL = 110
|
13
|
-
INVALID_INCLUDE = 112
|
14
|
-
RELATION_EXISTS = 113
|
15
|
-
INVALID_SORT_CRITERIA = 114
|
16
|
-
INVALID_LINKS_OBJECT = 115
|
17
|
-
TYPE_MISMATCH = 116
|
18
|
-
INVALID_PAGE_OBJECT = 117
|
19
|
-
INVALID_PAGE_VALUE = 118
|
20
|
-
INVALID_FIELD_FORMAT = 119
|
21
|
-
INVALID_FILTERS_SYNTAX = 120
|
22
|
-
SAVE_FAILED = 121
|
23
|
-
FORBIDDEN = 403
|
24
|
-
RECORD_NOT_FOUND = 404
|
25
|
-
UNSUPPORTED_MEDIA_TYPE = 415
|
26
|
-
LOCKED = 423
|
27
|
-
INTERNAL_SERVER_ERROR = 500
|
2
|
+
VALIDATION_ERROR = '100'
|
3
|
+
INVALID_RESOURCE = '101'
|
4
|
+
FILTER_NOT_ALLOWED = '102'
|
5
|
+
INVALID_FIELD_VALUE = '103'
|
6
|
+
INVALID_FIELD = '104'
|
7
|
+
PARAM_NOT_ALLOWED = '105'
|
8
|
+
PARAM_MISSING = '106'
|
9
|
+
INVALID_FILTER_VALUE = '107'
|
10
|
+
COUNT_MISMATCH = '108'
|
11
|
+
KEY_ORDER_MISMATCH = '109'
|
12
|
+
KEY_NOT_INCLUDED_IN_URL = '110'
|
13
|
+
INVALID_INCLUDE = '112'
|
14
|
+
RELATION_EXISTS = '113'
|
15
|
+
INVALID_SORT_CRITERIA = '114'
|
16
|
+
INVALID_LINKS_OBJECT = '115'
|
17
|
+
TYPE_MISMATCH = '116'
|
18
|
+
INVALID_PAGE_OBJECT = '117'
|
19
|
+
INVALID_PAGE_VALUE = '118'
|
20
|
+
INVALID_FIELD_FORMAT = '119'
|
21
|
+
INVALID_FILTERS_SYNTAX = '120'
|
22
|
+
SAVE_FAILED = '121'
|
23
|
+
FORBIDDEN = '403'
|
24
|
+
RECORD_NOT_FOUND = '404'
|
25
|
+
UNSUPPORTED_MEDIA_TYPE = '415'
|
26
|
+
LOCKED = '423'
|
27
|
+
INTERNAL_SERVER_ERROR = '500'
|
28
28
|
|
29
29
|
TEXT_ERRORS =
|
30
30
|
{ VALIDATION_ERROR => 'VALIDATION_ERROR',
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -18,8 +18,10 @@ module JSONAPI
|
|
18
18
|
|
19
19
|
[JSONAPI::Error.new(code: JSONAPI::INTERNAL_SERVER_ERROR,
|
20
20
|
status: :internal_server_error,
|
21
|
-
title: '
|
22
|
-
|
21
|
+
title: I18n.t('jsonapi-resources.exceptions.internal_server_error.title',
|
22
|
+
default: 'Internal Server Error'),
|
23
|
+
detail: I18n.t('jsonapi-resources.exceptions.internal_server_error.detail',
|
24
|
+
default: 'Internal Server Error'),
|
23
25
|
meta: meta)]
|
24
26
|
end
|
25
27
|
end
|
@@ -33,8 +35,10 @@ module JSONAPI
|
|
33
35
|
def errors
|
34
36
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_RESOURCE,
|
35
37
|
status: :bad_request,
|
36
|
-
title: '
|
37
|
-
|
38
|
+
title: I18n.t('jsonapi-resources.exceptions.invalid_resource.title',
|
39
|
+
default: 'Invalid resource'),
|
40
|
+
detail: I18n.t('jsonapi-resources.exceptions.invalid_resource.detail',
|
41
|
+
default: "#{resource} is not a valid resource.", resource: resource))]
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
@@ -47,8 +51,10 @@ module JSONAPI
|
|
47
51
|
def errors
|
48
52
|
[JSONAPI::Error.new(code: JSONAPI::RECORD_NOT_FOUND,
|
49
53
|
status: :not_found,
|
50
|
-
title: '
|
51
|
-
|
54
|
+
title: I18n.translate('jsonapi-resources.exceptions.record_not_found.title',
|
55
|
+
default: 'Record not found'),
|
56
|
+
detail: I18n.translate('jsonapi-resources.exceptions.record_not_found.detail',
|
57
|
+
default: "The record identified by #{id} could not be found.", id: id))]
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
@@ -61,8 +67,12 @@ module JSONAPI
|
|
61
67
|
def errors
|
62
68
|
[JSONAPI::Error.new(code: JSONAPI::UNSUPPORTED_MEDIA_TYPE,
|
63
69
|
status: :unsupported_media_type,
|
64
|
-
title: '
|
65
|
-
|
70
|
+
title: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.title',
|
71
|
+
default: 'Unsupported media type'),
|
72
|
+
detail: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.detail',
|
73
|
+
default: "All requests that create or update must use the '#{JSONAPI::MEDIA_TYPE}' Content-Type. This request specified '#{media_type}'.",
|
74
|
+
needed_media_type: JSONAPI::MEDIA_TYPE,
|
75
|
+
media_type: media_type))]
|
66
76
|
end
|
67
77
|
end
|
68
78
|
|
@@ -75,8 +85,11 @@ module JSONAPI
|
|
75
85
|
def errors
|
76
86
|
[JSONAPI::Error.new(code: JSONAPI::RELATION_EXISTS,
|
77
87
|
status: :bad_request,
|
78
|
-
title: '
|
79
|
-
|
88
|
+
title: I18n.translate('jsonapi-resources.exceptions.has_many_relation.title',
|
89
|
+
default: 'Relation exists'),
|
90
|
+
detail: I18n.translate('jsonapi-resources.exceptions.has_many_relation.detail',
|
91
|
+
default: "The relation to #{id} already exists.",
|
92
|
+
id: id))]
|
80
93
|
end
|
81
94
|
end
|
82
95
|
|
@@ -84,8 +97,10 @@ module JSONAPI
|
|
84
97
|
def errors
|
85
98
|
[JSONAPI::Error.new(code: JSONAPI::FORBIDDEN,
|
86
99
|
status: :forbidden,
|
87
|
-
title: '
|
88
|
-
|
100
|
+
title: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.title',
|
101
|
+
default: 'Complete replacement forbidden'),
|
102
|
+
detail: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.detail',
|
103
|
+
default: 'Complete replacement forbidden for this relationship'))]
|
89
104
|
end
|
90
105
|
end
|
91
106
|
|
@@ -98,8 +113,11 @@ module JSONAPI
|
|
98
113
|
def errors
|
99
114
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTERS_SYNTAX,
|
100
115
|
status: :bad_request,
|
101
|
-
title: '
|
102
|
-
|
116
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_filter_syntax.title',
|
117
|
+
default: 'Invalid filters syntax'),
|
118
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_filter_syntax.detail',
|
119
|
+
default: "#{filters} is not a valid syntax for filtering.",
|
120
|
+
filters: filters))]
|
103
121
|
end
|
104
122
|
end
|
105
123
|
|
@@ -112,8 +130,10 @@ module JSONAPI
|
|
112
130
|
def errors
|
113
131
|
[JSONAPI::Error.new(code: JSONAPI::FILTER_NOT_ALLOWED,
|
114
132
|
status: :bad_request,
|
115
|
-
title: '
|
116
|
-
|
133
|
+
title: I18n.translate('jsonapi-resources.exceptions.filter_not_allowed.title',
|
134
|
+
default: 'Filter not allowed'),
|
135
|
+
detail: I18n.translate('jsonapi-resources.exceptions.filter_not_allowed.detail',
|
136
|
+
default: "#{filter} is not allowed.", filter: filter))]
|
117
137
|
end
|
118
138
|
end
|
119
139
|
|
@@ -127,8 +147,11 @@ module JSONAPI
|
|
127
147
|
def errors
|
128
148
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTER_VALUE,
|
129
149
|
status: :bad_request,
|
130
|
-
title: '
|
131
|
-
|
150
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_filter_value.title',
|
151
|
+
default: 'Invalid filter value'),
|
152
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_filter_value.detail',
|
153
|
+
default: "#{value} is not a valid value for #{filter}.",
|
154
|
+
value: value, filter: filter))]
|
132
155
|
end
|
133
156
|
end
|
134
157
|
|
@@ -142,8 +165,11 @@ module JSONAPI
|
|
142
165
|
def errors
|
143
166
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD_VALUE,
|
144
167
|
status: :bad_request,
|
145
|
-
title: '
|
146
|
-
|
168
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_field_value.title',
|
169
|
+
default: 'Invalid field value'),
|
170
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field_value.detail',
|
171
|
+
default: "#{value} is not a valid value for #{field}.",
|
172
|
+
value: value, field: field))]
|
147
173
|
end
|
148
174
|
end
|
149
175
|
|
@@ -151,8 +177,10 @@ module JSONAPI
|
|
151
177
|
def errors
|
152
178
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD_FORMAT,
|
153
179
|
status: :bad_request,
|
154
|
-
title: '
|
155
|
-
|
180
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_field_format.title',
|
181
|
+
default: 'Invalid field format'),
|
182
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field_format.detail',
|
183
|
+
default: 'Fields must specify a type.'))]
|
156
184
|
end
|
157
185
|
end
|
158
186
|
|
@@ -160,8 +188,10 @@ module JSONAPI
|
|
160
188
|
def errors
|
161
189
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_LINKS_OBJECT,
|
162
190
|
status: :bad_request,
|
163
|
-
title: '
|
164
|
-
|
191
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_links_object.title',
|
192
|
+
default: 'Invalid Links Object'),
|
193
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_links_object.detail',
|
194
|
+
default: 'Data is not a valid Links Object.'))]
|
165
195
|
end
|
166
196
|
end
|
167
197
|
|
@@ -174,8 +204,10 @@ module JSONAPI
|
|
174
204
|
def errors
|
175
205
|
[JSONAPI::Error.new(code: JSONAPI::TYPE_MISMATCH,
|
176
206
|
status: :bad_request,
|
177
|
-
title: '
|
178
|
-
|
207
|
+
title: I18n.translate('jsonapi-resources.exceptions.type_mismatch.title',
|
208
|
+
default: 'Type Mismatch'),
|
209
|
+
detail: I18n.translate('jsonapi-resources.exceptions.type_mismatch.detail',
|
210
|
+
default: "#{type} is not a valid type for this operation.", type: type))]
|
179
211
|
end
|
180
212
|
end
|
181
213
|
|
@@ -189,8 +221,11 @@ module JSONAPI
|
|
189
221
|
def errors
|
190
222
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD,
|
191
223
|
status: :bad_request,
|
192
|
-
title: '
|
193
|
-
|
224
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_field.title',
|
225
|
+
default: 'Invalid field'),
|
226
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field.detail',
|
227
|
+
default: "#{field} is not a valid field for #{type}.",
|
228
|
+
field: field, type: type))]
|
194
229
|
end
|
195
230
|
end
|
196
231
|
|
@@ -204,8 +239,11 @@ module JSONAPI
|
|
204
239
|
def errors
|
205
240
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_INCLUDE,
|
206
241
|
status: :bad_request,
|
207
|
-
title: '
|
208
|
-
|
242
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_include.title',
|
243
|
+
default: 'Invalid field'),
|
244
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_include.detail',
|
245
|
+
default: "#{relationship} is not a valid relationship of #{resource}",
|
246
|
+
relationship: relationship, resource: resource))]
|
209
247
|
end
|
210
248
|
end
|
211
249
|
|
@@ -219,8 +257,11 @@ module JSONAPI
|
|
219
257
|
def errors
|
220
258
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_SORT_CRITERIA,
|
221
259
|
status: :bad_request,
|
222
|
-
title: '
|
223
|
-
|
260
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_sort_criteria.title',
|
261
|
+
default: 'Invalid sort criteria'),
|
262
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_sort_criteria.detail',
|
263
|
+
default: "#{sort_criteria} is not a valid sort criteria for #{resource}",
|
264
|
+
sort_criteria: sort_criteria, resource: resource))]
|
224
265
|
end
|
225
266
|
end
|
226
267
|
|
@@ -234,8 +275,11 @@ module JSONAPI
|
|
234
275
|
params.collect do |param|
|
235
276
|
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
|
236
277
|
status: :bad_request,
|
237
|
-
title: '
|
238
|
-
|
278
|
+
title: I18n.translate('jsonapi-resources.exceptions.parameters_not_allowed.title',
|
279
|
+
default: 'Param not allowed'),
|
280
|
+
detail: I18n.translate('jsonapi-resources.exceptions.parameters_not_allowed.detail',
|
281
|
+
default: "#{param} is not allowed.", param: param))
|
282
|
+
|
239
283
|
end
|
240
284
|
end
|
241
285
|
end
|
@@ -249,8 +293,10 @@ module JSONAPI
|
|
249
293
|
def errors
|
250
294
|
[JSONAPI::Error.new(code: JSONAPI::PARAM_MISSING,
|
251
295
|
status: :bad_request,
|
252
|
-
title: '
|
253
|
-
|
296
|
+
title: I18n.translate('jsonapi-resources.exceptions.parameter_missing.title',
|
297
|
+
default: 'Missing Parameter'),
|
298
|
+
detail: I18n.translate('jsonapi-resources.exceptions.parameter_missing.detail',
|
299
|
+
default: "The required parameter, #{param}, is missing.", param: param))]
|
254
300
|
end
|
255
301
|
end
|
256
302
|
|
@@ -258,8 +304,10 @@ module JSONAPI
|
|
258
304
|
def errors
|
259
305
|
[JSONAPI::Error.new(code: JSONAPI::COUNT_MISMATCH,
|
260
306
|
status: :bad_request,
|
261
|
-
title: '
|
262
|
-
|
307
|
+
title: I18n.translate('jsonapi-resources.exceptions.count_mismatch.title',
|
308
|
+
default: 'Count to key mismatch'),
|
309
|
+
detail: I18n.translate('jsonapi-resources.exceptions.count_mismatch.detail',
|
310
|
+
default: 'The resource collection does not contain the same number of objects as the number of keys.'))]
|
263
311
|
end
|
264
312
|
end
|
265
313
|
|
@@ -272,8 +320,11 @@ module JSONAPI
|
|
272
320
|
def errors
|
273
321
|
[JSONAPI::Error.new(code: JSONAPI::KEY_NOT_INCLUDED_IN_URL,
|
274
322
|
status: :bad_request,
|
275
|
-
title: '
|
276
|
-
|
323
|
+
title: I18n.translate('jsonapi-resources.exceptions.key_not_included_in_url.title',
|
324
|
+
default: 'Key is not included in URL'),
|
325
|
+
detail: I18n.translate('jsonapi-resources.exceptions.key_not_included_in_url.detail',
|
326
|
+
default: "The URL does not support the key #{key}",
|
327
|
+
key: key))]
|
277
328
|
end
|
278
329
|
end
|
279
330
|
|
@@ -281,8 +332,10 @@ module JSONAPI
|
|
281
332
|
def errors
|
282
333
|
[JSONAPI::Error.new(code: JSONAPI::KEY_ORDER_MISMATCH,
|
283
334
|
status: :bad_request,
|
284
|
-
title: '
|
285
|
-
|
335
|
+
title: I18n.translate('jsonapi-resources.exceptions.missing_key.title',
|
336
|
+
default: 'A key is required'),
|
337
|
+
detail: I18n.translate('jsonapi-resources.exceptions.missing_key.detail',
|
338
|
+
default: 'The resource object does not contain a key.'))]
|
286
339
|
end
|
287
340
|
end
|
288
341
|
|
@@ -295,16 +348,18 @@ module JSONAPI
|
|
295
348
|
def errors
|
296
349
|
[JSONAPI::Error.new(code: JSONAPI::LOCKED,
|
297
350
|
status: :locked,
|
298
|
-
title: '
|
351
|
+
title: I18n.translate('jsonapi-resources.exceptions.record_locked.title',
|
352
|
+
default: 'Locked resource'),
|
299
353
|
detail: "#{message}")]
|
300
354
|
end
|
301
355
|
end
|
302
356
|
|
303
357
|
class ValidationErrors < Error
|
304
|
-
attr_reader :error_messages, :resource_relationships
|
358
|
+
attr_reader :error_messages, :error_metadata, :resource_relationships
|
305
359
|
|
306
360
|
def initialize(resource)
|
307
361
|
@error_messages = resource.model_error_messages
|
362
|
+
@error_metadata = resource.validation_error_metadata
|
308
363
|
@resource_relationships = resource.class._relationships.keys
|
309
364
|
@key_formatter = JSONAPI.configuration.key_formatter
|
310
365
|
end
|
@@ -326,7 +381,13 @@ module JSONAPI
|
|
326
381
|
status: :unprocessable_entity,
|
327
382
|
title: message,
|
328
383
|
detail: "#{format_key(attr_key)} - #{message}",
|
329
|
-
source: { pointer: pointer(attr_key) }
|
384
|
+
source: { pointer: pointer(attr_key) },
|
385
|
+
meta: metadata_for(attr_key, message))
|
386
|
+
end
|
387
|
+
|
388
|
+
def metadata_for(attr_key, message)
|
389
|
+
return if error_metadata.nil?
|
390
|
+
error_metadata[attr_key] ? error_metadata[attr_key][message] : nil
|
330
391
|
end
|
331
392
|
|
332
393
|
def pointer(attr_or_relationship_name)
|
@@ -343,8 +404,10 @@ module JSONAPI
|
|
343
404
|
def errors
|
344
405
|
[JSONAPI::Error.new(code: JSONAPI::SAVE_FAILED,
|
345
406
|
status: :unprocessable_entity,
|
346
|
-
title: '
|
347
|
-
|
407
|
+
title: I18n.translate('jsonapi-resources.exceptions.save_failed.title',
|
408
|
+
default: 'Save failed or was cancelled'),
|
409
|
+
detail: I18n.translate('jsonapi-resources.exceptions.save_failed.detail',
|
410
|
+
default: 'Save failed or was cancelled'))]
|
348
411
|
end
|
349
412
|
end
|
350
413
|
|
@@ -352,8 +415,10 @@ module JSONAPI
|
|
352
415
|
def errors
|
353
416
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_PAGE_OBJECT,
|
354
417
|
status: :bad_request,
|
355
|
-
title: '
|
356
|
-
|
418
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_page_object.title',
|
419
|
+
default: 'Invalid Page Object'),
|
420
|
+
detail: I18n.translate('jsonapi-resources.exceptions.invalid_page_object.detail',
|
421
|
+
default: 'Invalid Page Object.'))]
|
357
422
|
end
|
358
423
|
end
|
359
424
|
|
@@ -367,8 +432,11 @@ module JSONAPI
|
|
367
432
|
params.collect do |param|
|
368
433
|
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
|
369
434
|
status: :bad_request,
|
370
|
-
title: '
|
371
|
-
|
435
|
+
title: I18n.translate('jsonapi-resources.exceptions.page_parameters_not_allowed.title',
|
436
|
+
default: 'Page parameter not allowed'),
|
437
|
+
detail: I18n.translate('jsonapi-resources.exceptions.page_parameters_not_allowed.detail',
|
438
|
+
default: "#{param} is not an allowed page parameter.",
|
439
|
+
param: param))
|
372
440
|
end
|
373
441
|
end
|
374
442
|
end
|
@@ -378,13 +446,16 @@ module JSONAPI
|
|
378
446
|
def initialize(page, value, msg = nil)
|
379
447
|
@page = page
|
380
448
|
@value = value
|
381
|
-
@msg = msg ||
|
449
|
+
@msg = msg || I18n.translate('jsonapi-resources.exceptions.invalid_page_value.detail',
|
450
|
+
default: "#{value} is not a valid value for #{page} page parameter.",
|
451
|
+
value: value, page: page)
|
382
452
|
end
|
383
453
|
|
384
454
|
def errors
|
385
455
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_PAGE_VALUE,
|
386
456
|
status: :bad_request,
|
387
|
-
title: '
|
457
|
+
title: I18n.translate('jsonapi-resources.exceptions.invalid_page_value.title',
|
458
|
+
default: 'Invalid page value'),
|
388
459
|
detail: @msg)]
|
389
460
|
end
|
390
461
|
end
|