jsonapi-resources 0.4.2 → 0.4.3
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/Gemfile +2 -2
- data/README.md +103 -71
- data/Rakefile +2 -2
- data/jsonapi-resources.gemspec +2 -2
- data/lib/jsonapi-resources.rb +0 -1
- data/lib/jsonapi/active_record_operations_processor.rb +10 -2
- data/lib/jsonapi/acts_as_resource_controller.rb +26 -24
- data/lib/jsonapi/association.rb +50 -15
- data/lib/jsonapi/callbacks.rb +1 -2
- data/lib/jsonapi/configuration.rb +8 -24
- data/lib/jsonapi/error.rb +1 -2
- data/lib/jsonapi/error_codes.rb +3 -1
- data/lib/jsonapi/exceptions.rb +59 -47
- data/lib/jsonapi/include_directives.rb +11 -11
- data/lib/jsonapi/mime_types.rb +2 -2
- data/lib/jsonapi/operation.rb +28 -11
- data/lib/jsonapi/operations_processor.rb +16 -5
- data/lib/jsonapi/paginator.rb +19 -19
- data/lib/jsonapi/request.rb +175 -196
- data/lib/jsonapi/resource.rb +158 -105
- data/lib/jsonapi/resource_serializer.rb +37 -26
- data/lib/jsonapi/resources/version.rb +2 -2
- data/lib/jsonapi/response_document.rb +5 -4
- data/lib/jsonapi/routing_ext.rb +24 -19
- data/test/controllers/controller_test.rb +261 -31
- data/test/fixtures/active_record.rb +206 -8
- data/test/fixtures/book_comments.yml +2 -1
- data/test/fixtures/books.yml +1 -0
- data/test/fixtures/documents.yml +3 -0
- data/test/fixtures/people.yml +8 -1
- data/test/fixtures/pictures.yml +15 -0
- data/test/fixtures/products.yml +3 -0
- data/test/fixtures/vehicles.yml +8 -0
- data/test/helpers/{hash_helpers.rb → assertions.rb} +6 -1
- data/test/integration/requests/request_test.rb +14 -3
- data/test/integration/routes/routes_test.rb +47 -0
- data/test/test_helper.rb +27 -4
- data/test/unit/serializer/include_directives_test.rb +5 -0
- data/test/unit/serializer/polymorphic_serializer_test.rb +384 -0
- data/test/unit/serializer/serializer_test.rb +19 -1
- metadata +14 -4
data/Rakefile
CHANGED
data/jsonapi-resources.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = JSONAPI::Resources::VERSION
|
9
9
|
spec.authors = ['Dan Gebhardt', 'Larry Gebhardt']
|
10
10
|
spec.email = ['dan@cerebris.com', 'larry@cerebris.com']
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
11
|
+
spec.summary = 'Easily support JSON API in Rails.'
|
12
|
+
spec.description = 'A resource-centric approach to implementing the controllers, routes, and serializers needed to support the JSON API spec.'
|
13
13
|
spec.homepage = 'https://github.com/cerebris/jsonapi-resources'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
data/lib/jsonapi-resources.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
|
2
|
-
|
3
2
|
private
|
3
|
+
|
4
4
|
def transaction
|
5
5
|
if @transactional
|
6
6
|
ActiveRecord::Base.transaction do
|
@@ -12,7 +12,7 @@ class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def rollback
|
15
|
-
|
15
|
+
fail ActiveRecord::Rollback if @transactional
|
16
16
|
end
|
17
17
|
|
18
18
|
def process_operation(operation)
|
@@ -24,5 +24,13 @@ class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
|
|
24
24
|
rescue ActiveRecord::RecordNotFound
|
25
25
|
record_not_found = JSONAPI::Exceptions::RecordNotFound.new(operation.associated_key)
|
26
26
|
return JSONAPI::ErrorsOperationResult.new(record_not_found.errors[0].code, record_not_found.errors)
|
27
|
+
|
28
|
+
rescue JSONAPI::Exceptions::Error => e
|
29
|
+
raise e
|
30
|
+
|
31
|
+
rescue => e
|
32
|
+
internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
|
33
|
+
Rails.logger.error { "Internal Server Error: #{e.message} #{e.backtrace.join("\n")}" }
|
34
|
+
return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
|
27
35
|
end
|
28
36
|
end
|
@@ -6,7 +6,7 @@ module JSONAPI
|
|
6
6
|
|
7
7
|
included do
|
8
8
|
before_filter :ensure_correct_media_type, only: [:create, :update, :create_association, :update_association]
|
9
|
-
|
9
|
+
append_before_filter :setup_request
|
10
10
|
after_filter :setup_response
|
11
11
|
end
|
12
12
|
|
@@ -60,6 +60,7 @@ module JSONAPI
|
|
60
60
|
end
|
61
61
|
|
62
62
|
private
|
63
|
+
|
63
64
|
def resource_klass
|
64
65
|
@resource_klass ||= resource_klass_name.safe_constantize
|
65
66
|
end
|
@@ -78,17 +79,14 @@ module JSONAPI
|
|
78
79
|
|
79
80
|
def ensure_correct_media_type
|
80
81
|
unless request.content_type == JSONAPI::MEDIA_TYPE
|
81
|
-
|
82
|
+
fail JSONAPI::Exceptions::UnsupportedMediaTypeError.new(request.content_type)
|
82
83
|
end
|
83
84
|
rescue => e
|
84
85
|
handle_exceptions(e)
|
85
86
|
end
|
86
87
|
|
87
88
|
def setup_request
|
88
|
-
@request = JSONAPI::Request.new(params,
|
89
|
-
context: context,
|
90
|
-
key_formatter: key_formatter
|
91
|
-
})
|
89
|
+
@request = JSONAPI::Request.new(params, context: context, key_formatter: key_formatter)
|
92
90
|
render_errors(@request.errors) unless @request.errors.empty?
|
93
91
|
rescue => e
|
94
92
|
handle_exceptions(e)
|
@@ -105,6 +103,11 @@ module JSONAPI
|
|
105
103
|
{}
|
106
104
|
end
|
107
105
|
|
106
|
+
# override to set scope_id
|
107
|
+
def scope_id
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
108
111
|
# Control by setting in an initializer:
|
109
112
|
# JSONAPI.configuration.json_key_format = :camelized_key
|
110
113
|
# JSONAPI.configuration.route = :camelized_route
|
@@ -128,7 +131,7 @@ module JSONAPI
|
|
128
131
|
end
|
129
132
|
|
130
133
|
def render_errors(errors)
|
131
|
-
operation_results = JSONAPI::OperationResults.new
|
134
|
+
operation_results = JSONAPI::OperationResults.new
|
132
135
|
result = JSONAPI::ErrorsOperationResult.new(errors[0].status, errors)
|
133
136
|
operation_results.add_result(result)
|
134
137
|
|
@@ -143,18 +146,17 @@ module JSONAPI
|
|
143
146
|
def create_response_document(operation_results)
|
144
147
|
JSONAPI::ResponseDocument.new(
|
145
148
|
operation_results,
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
}
|
149
|
+
primary_resource_klass: resource_klass,
|
150
|
+
include_directives: @request ? @request.include_directives : nil,
|
151
|
+
fields: @request ? @request.fields : nil,
|
152
|
+
base_url: base_url,
|
153
|
+
key_formatter: key_formatter,
|
154
|
+
route_formatter: route_formatter,
|
155
|
+
base_meta: base_response_meta,
|
156
|
+
base_links: base_response_links,
|
157
|
+
resource_serializer_klass: resource_serializer_klass,
|
158
|
+
request: @request,
|
159
|
+
scope_id: scope_id
|
158
160
|
)
|
159
161
|
end
|
160
162
|
|
@@ -169,11 +171,11 @@ module JSONAPI
|
|
169
171
|
# Note: Be sure to either call super(e) or handle JSONAPI::Exceptions::Error and raise unhandled exceptions
|
170
172
|
def handle_exceptions(e)
|
171
173
|
case e
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
when JSONAPI::Exceptions::Error
|
175
|
+
render_errors(e.errors)
|
176
|
+
else # raise all other exceptions
|
177
|
+
# :nocov:
|
178
|
+
fail e
|
177
179
|
# :nocov:
|
178
180
|
end
|
179
181
|
end
|
data/lib/jsonapi/association.rb
CHANGED
@@ -1,34 +1,69 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
class Association
|
3
|
-
attr_reader :acts_as_set, :foreign_key, :type, :options, :name,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
3
|
+
attr_reader :acts_as_set, :foreign_key, :type, :options, :name,
|
4
|
+
:class_name, :polymorphic
|
5
|
+
|
6
|
+
def initialize(name, options = {})
|
7
|
+
@name = name.to_s
|
8
|
+
@options = options
|
9
|
+
@acts_as_set = options.fetch(:acts_as_set, false) == true
|
10
|
+
@foreign_key = options[:foreign_key] ? options[:foreign_key].to_sym : nil
|
11
|
+
@module_path = options[:module_path] || ''
|
12
|
+
@relation_name = options.fetch(:relation_name, @name)
|
13
|
+
@polymorphic = options.fetch(:polymorphic, false) == true
|
11
14
|
end
|
12
15
|
|
16
|
+
alias_method :polymorphic?, :polymorphic
|
17
|
+
|
13
18
|
def primary_key
|
14
|
-
@primary_key ||=
|
19
|
+
@primary_key ||= resource_klass._primary_key
|
20
|
+
end
|
21
|
+
|
22
|
+
def resource_klass
|
23
|
+
@resource_klass ||= Resource.resource_for(@module_path + @class_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def relation_name(options = {})
|
27
|
+
case @relation_name
|
28
|
+
when Symbol
|
29
|
+
# :nocov:
|
30
|
+
@relation_name
|
31
|
+
# :nocov:
|
32
|
+
when String
|
33
|
+
@relation_name.to_sym
|
34
|
+
when Proc
|
35
|
+
@relation_name.call(options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def type_for_source(source)
|
40
|
+
if polymorphic?
|
41
|
+
resource = source.public_send(name)
|
42
|
+
resource.class._type if resource
|
43
|
+
else
|
44
|
+
type
|
45
|
+
end
|
15
46
|
end
|
16
47
|
|
17
48
|
class HasOne < Association
|
18
|
-
def initialize(name, options={})
|
49
|
+
def initialize(name, options = {})
|
19
50
|
super
|
20
|
-
@class_name = options.fetch(:class_name, name.to_s.
|
51
|
+
@class_name = options.fetch(:class_name, name.to_s.camelize)
|
21
52
|
@type = class_name.underscore.pluralize.to_sym
|
22
|
-
@foreign_key ||=
|
53
|
+
@foreign_key ||= "#{name}_id".to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
def polymorphic_type
|
57
|
+
"#{type.to_s.singularize}_type" if polymorphic?
|
23
58
|
end
|
24
59
|
end
|
25
60
|
|
26
61
|
class HasMany < Association
|
27
|
-
def initialize(name, options={})
|
62
|
+
def initialize(name, options = {})
|
28
63
|
super
|
29
|
-
@class_name = options.fetch(:class_name, name.to_s.
|
64
|
+
@class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
|
30
65
|
@type = class_name.underscore.pluralize.to_sym
|
31
|
-
@foreign_key
|
66
|
+
@foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
|
32
67
|
end
|
33
68
|
end
|
34
69
|
end
|
data/lib/jsonapi/callbacks.rb
CHANGED
@@ -62,37 +62,21 @@ module JSONAPI
|
|
62
62
|
@operations_processor = JSONAPI::OperationsProcessor.operations_processor_for(@operations_processor_name)
|
63
63
|
end
|
64
64
|
|
65
|
-
|
66
|
-
@allowed_request_params = allowed_request_params
|
67
|
-
end
|
65
|
+
attr_writer :allowed_request_params
|
68
66
|
|
69
|
-
|
70
|
-
@default_paginator = default_paginator
|
71
|
-
end
|
67
|
+
attr_writer :default_paginator
|
72
68
|
|
73
|
-
|
74
|
-
@default_page_size = default_page_size
|
75
|
-
end
|
69
|
+
attr_writer :default_page_size
|
76
70
|
|
77
|
-
|
78
|
-
@maximum_page_size = maximum_page_size
|
79
|
-
end
|
71
|
+
attr_writer :maximum_page_size
|
80
72
|
|
81
|
-
|
82
|
-
@use_text_errors = use_text_errors
|
83
|
-
end
|
73
|
+
attr_writer :use_text_errors
|
84
74
|
|
85
|
-
|
86
|
-
@top_level_links_include_pagination = top_level_links_include_pagination
|
87
|
-
end
|
75
|
+
attr_writer :top_level_links_include_pagination
|
88
76
|
|
89
|
-
|
90
|
-
@top_level_meta_include_record_count = top_level_meta_include_record_count
|
91
|
-
end
|
77
|
+
attr_writer :top_level_meta_include_record_count
|
92
78
|
|
93
|
-
|
94
|
-
@top_level_meta_record_count_key = top_level_meta_record_count_key
|
95
|
-
end
|
79
|
+
attr_writer :top_level_meta_record_count_key
|
96
80
|
end
|
97
81
|
|
98
82
|
class << self
|
data/lib/jsonapi/error.rb
CHANGED
data/lib/jsonapi/error_codes.rb
CHANGED
@@ -24,6 +24,7 @@ module JSONAPI
|
|
24
24
|
RECORD_NOT_FOUND = 404
|
25
25
|
UNSUPPORTED_MEDIA_TYPE = 415
|
26
26
|
LOCKED = 423
|
27
|
+
INTERNAL_SERVER_ERROR = 500
|
27
28
|
|
28
29
|
TEXT_ERRORS =
|
29
30
|
{ VALIDATION_ERROR => 'VALIDATION_ERROR',
|
@@ -50,6 +51,7 @@ module JSONAPI
|
|
50
51
|
FORBIDDEN => 'FORBIDDEN',
|
51
52
|
RECORD_NOT_FOUND => 'RECORD_NOT_FOUND',
|
52
53
|
UNSUPPORTED_MEDIA_TYPE => 'UNSUPPORTED_MEDIA_TYPE',
|
53
|
-
LOCKED => 'LOCKED'
|
54
|
+
LOCKED => 'LOCKED',
|
55
|
+
INTERNAL_SERVER_ERROR => 'INTERNAL_SERVER_ERROR'
|
54
56
|
}
|
55
57
|
end
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -2,6 +2,21 @@ module JSONAPI
|
|
2
2
|
module Exceptions
|
3
3
|
class Error < RuntimeError; end
|
4
4
|
|
5
|
+
class InternalServerError < Error
|
6
|
+
attr_accessor :exception
|
7
|
+
|
8
|
+
def initialize(exception)
|
9
|
+
@exception = exception
|
10
|
+
end
|
11
|
+
|
12
|
+
def errors
|
13
|
+
[JSONAPI::Error.new(code: JSONAPI::INTERNAL_SERVER_ERROR,
|
14
|
+
status: 500,
|
15
|
+
title: 'Internal Server Error',
|
16
|
+
detail: 'Internal Server Error')]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
5
20
|
class InvalidResource < Error
|
6
21
|
attr_accessor :resource
|
7
22
|
def initialize(resource)
|
@@ -10,9 +25,9 @@ module JSONAPI
|
|
10
25
|
|
11
26
|
def errors
|
12
27
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_RESOURCE,
|
13
|
-
|
14
|
-
|
15
|
-
|
28
|
+
status: :bad_request,
|
29
|
+
title: 'Invalid resource',
|
30
|
+
detail: "#{resource} is not a valid resource.")]
|
16
31
|
end
|
17
32
|
end
|
18
33
|
|
@@ -24,9 +39,9 @@ module JSONAPI
|
|
24
39
|
|
25
40
|
def errors
|
26
41
|
[JSONAPI::Error.new(code: JSONAPI::RECORD_NOT_FOUND,
|
27
|
-
|
28
|
-
|
29
|
-
|
42
|
+
status: :not_found,
|
43
|
+
title: 'Record not found',
|
44
|
+
detail: "The record identified by #{id} could not be found.")]
|
30
45
|
end
|
31
46
|
end
|
32
47
|
|
@@ -38,9 +53,9 @@ module JSONAPI
|
|
38
53
|
|
39
54
|
def errors
|
40
55
|
[JSONAPI::Error.new(code: JSONAPI::UNSUPPORTED_MEDIA_TYPE,
|
41
|
-
|
42
|
-
|
43
|
-
|
56
|
+
status: :unsupported_media_type,
|
57
|
+
title: 'Unsupported media type',
|
58
|
+
detail: "All requests that create or update resources must use the '#{JSONAPI::MEDIA_TYPE}' Content-Type. This request specified '#{media_type}.'")]
|
44
59
|
end
|
45
60
|
end
|
46
61
|
|
@@ -75,9 +90,9 @@ module JSONAPI
|
|
75
90
|
|
76
91
|
def errors
|
77
92
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTERS_SYNTAX,
|
78
|
-
|
79
|
-
|
80
|
-
|
93
|
+
status: :bad_request,
|
94
|
+
title: 'Invalid filters syntax',
|
95
|
+
detail: "#{filters} is not a valid syntax for filtering.")]
|
81
96
|
end
|
82
97
|
end
|
83
98
|
|
@@ -89,9 +104,9 @@ module JSONAPI
|
|
89
104
|
|
90
105
|
def errors
|
91
106
|
[JSONAPI::Error.new(code: JSONAPI::FILTER_NOT_ALLOWED,
|
92
|
-
|
93
|
-
|
94
|
-
|
107
|
+
status: :bad_request,
|
108
|
+
title: 'Filter not allowed',
|
109
|
+
detail: "#{filter} is not allowed.")]
|
95
110
|
end
|
96
111
|
end
|
97
112
|
|
@@ -104,9 +119,9 @@ module JSONAPI
|
|
104
119
|
|
105
120
|
def errors
|
106
121
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTER_VALUE,
|
107
|
-
|
108
|
-
|
109
|
-
|
122
|
+
status: :bad_request,
|
123
|
+
title: 'Invalid filter value',
|
124
|
+
detail: "#{value} is not a valid value for #{filter}.")]
|
110
125
|
end
|
111
126
|
end
|
112
127
|
|
@@ -119,9 +134,9 @@ module JSONAPI
|
|
119
134
|
|
120
135
|
def errors
|
121
136
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD_VALUE,
|
122
|
-
|
123
|
-
|
124
|
-
|
137
|
+
status: :bad_request,
|
138
|
+
title: 'Invalid field value',
|
139
|
+
detail: "#{value} is not a valid value for #{field}.")]
|
125
140
|
end
|
126
141
|
end
|
127
142
|
|
@@ -166,9 +181,9 @@ module JSONAPI
|
|
166
181
|
|
167
182
|
def errors
|
168
183
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD,
|
169
|
-
|
170
|
-
|
171
|
-
|
184
|
+
status: :bad_request,
|
185
|
+
title: 'Invalid field',
|
186
|
+
detail: "#{field} is not a valid field for #{type}.")]
|
172
187
|
end
|
173
188
|
end
|
174
189
|
|
@@ -209,13 +224,12 @@ module JSONAPI
|
|
209
224
|
end
|
210
225
|
|
211
226
|
def errors
|
212
|
-
|
213
|
-
|
227
|
+
params.collect do |param|
|
228
|
+
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
|
214
229
|
status: :bad_request,
|
215
230
|
title: 'Param not allowed',
|
216
231
|
detail: "#{param} is not allowed.")
|
217
|
-
|
218
|
-
|
232
|
+
end
|
219
233
|
end
|
220
234
|
end
|
221
235
|
|
@@ -227,18 +241,18 @@ module JSONAPI
|
|
227
241
|
|
228
242
|
def errors
|
229
243
|
[JSONAPI::Error.new(code: JSONAPI::PARAM_MISSING,
|
230
|
-
|
231
|
-
|
232
|
-
|
244
|
+
status: :bad_request,
|
245
|
+
title: 'Missing Parameter',
|
246
|
+
detail: "The required parameter, #{param}, is missing.")]
|
233
247
|
end
|
234
248
|
end
|
235
249
|
|
236
250
|
class CountMismatch < Error
|
237
251
|
def errors
|
238
252
|
[JSONAPI::Error.new(code: JSONAPI::COUNT_MISMATCH,
|
239
|
-
|
240
|
-
|
241
|
-
|
253
|
+
status: :bad_request,
|
254
|
+
title: 'Count to key mismatch',
|
255
|
+
detail: 'The resource collection does not contain the same number of objects as the number of keys.')]
|
242
256
|
end
|
243
257
|
end
|
244
258
|
|
@@ -250,18 +264,18 @@ module JSONAPI
|
|
250
264
|
|
251
265
|
def errors
|
252
266
|
[JSONAPI::Error.new(code: JSONAPI::KEY_NOT_INCLUDED_IN_URL,
|
253
|
-
|
254
|
-
|
255
|
-
|
267
|
+
status: :bad_request,
|
268
|
+
title: 'Key is not included in URL',
|
269
|
+
detail: "The URL does not support the key #{key}")]
|
256
270
|
end
|
257
271
|
end
|
258
272
|
|
259
273
|
class MissingKey < Error
|
260
274
|
def errors
|
261
275
|
[JSONAPI::Error.new(code: JSONAPI::KEY_ORDER_MISMATCH,
|
262
|
-
|
263
|
-
|
264
|
-
|
276
|
+
status: :bad_request,
|
277
|
+
title: 'A key is required',
|
278
|
+
detail: 'The resource object does not contain a key.')]
|
265
279
|
end
|
266
280
|
end
|
267
281
|
|
@@ -273,9 +287,9 @@ module JSONAPI
|
|
273
287
|
|
274
288
|
def errors
|
275
289
|
[JSONAPI::Error.new(code: JSONAPI::LOCKED,
|
276
|
-
|
277
|
-
|
278
|
-
|
290
|
+
status: :locked,
|
291
|
+
title: 'Locked resource',
|
292
|
+
detail: "#{message}")]
|
279
293
|
end
|
280
294
|
end
|
281
295
|
|
@@ -323,7 +337,6 @@ module JSONAPI
|
|
323
337
|
end
|
324
338
|
end
|
325
339
|
|
326
|
-
|
327
340
|
class PageParametersNotAllowed < Error
|
328
341
|
attr_accessor :params
|
329
342
|
def initialize(params)
|
@@ -331,13 +344,12 @@ module JSONAPI
|
|
331
344
|
end
|
332
345
|
|
333
346
|
def errors
|
334
|
-
params.collect
|
347
|
+
params.collect do |param|
|
335
348
|
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
|
336
349
|
status: :bad_request,
|
337
350
|
title: 'Page parameter not allowed',
|
338
351
|
detail: "#{param} is not an allowed page parameter.")
|
339
|
-
|
340
|
-
|
352
|
+
end
|
341
353
|
end
|
342
354
|
end
|
343
355
|
|