jsonapi-resources 0.7.0 → 0.7.1.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 +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
|