jsonapi-resources 0.9.11 → 0.10.7

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +34 -11
  4. data/lib/bug_report_templates/rails_5_latest.rb +125 -0
  5. data/lib/bug_report_templates/rails_5_master.rb +140 -0
  6. data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +27 -0
  7. data/lib/jsonapi/active_relation/join_manager.rb +303 -0
  8. data/lib/jsonapi/active_relation_resource.rb +884 -0
  9. data/lib/jsonapi/acts_as_resource_controller.rb +122 -106
  10. data/lib/jsonapi/basic_resource.rb +1162 -0
  11. data/lib/jsonapi/cached_response_fragment.rb +127 -0
  12. data/lib/jsonapi/compiled_json.rb +11 -1
  13. data/lib/jsonapi/configuration.rb +57 -8
  14. data/lib/jsonapi/error.rb +27 -0
  15. data/lib/jsonapi/error_codes.rb +2 -0
  16. data/lib/jsonapi/exceptions.rb +63 -40
  17. data/lib/jsonapi/formatter.rb +3 -3
  18. data/lib/jsonapi/include_directives.rb +18 -75
  19. data/lib/jsonapi/link_builder.rb +16 -19
  20. data/lib/jsonapi/operation.rb +16 -5
  21. data/lib/jsonapi/operation_result.rb +73 -15
  22. data/lib/jsonapi/paginator.rb +17 -0
  23. data/lib/jsonapi/path.rb +43 -0
  24. data/lib/jsonapi/path_segment.rb +76 -0
  25. data/lib/jsonapi/processor.rb +246 -111
  26. data/lib/jsonapi/relationship.rb +117 -18
  27. data/lib/jsonapi/request_parser.rb +383 -396
  28. data/lib/jsonapi/resource.rb +3 -1376
  29. data/lib/jsonapi/resource_controller_metal.rb +5 -2
  30. data/lib/jsonapi/resource_fragment.rb +47 -0
  31. data/lib/jsonapi/resource_id_tree.rb +112 -0
  32. data/lib/jsonapi/resource_identity.rb +42 -0
  33. data/lib/jsonapi/resource_serializer.rb +124 -286
  34. data/lib/jsonapi/resource_set.rb +176 -0
  35. data/lib/jsonapi/resources/railtie.rb +9 -0
  36. data/lib/jsonapi/resources/version.rb +1 -1
  37. data/lib/jsonapi/response_document.rb +104 -87
  38. data/lib/jsonapi/routing_ext.rb +19 -21
  39. data/lib/jsonapi-resources.rb +20 -4
  40. data/lib/tasks/check_upgrade.rake +52 -0
  41. metadata +36 -33
  42. data/lib/jsonapi/cached_resource_fragment.rb +0 -127
  43. data/lib/jsonapi/operation_dispatcher.rb +0 -88
  44. data/lib/jsonapi/operation_results.rb +0 -35
  45. data/lib/jsonapi/relationship_builder.rb +0 -167
@@ -0,0 +1,127 @@
1
+ module JSONAPI
2
+ class CachedResponseFragment
3
+
4
+ Lookup = Struct.new(:resource_klass, :serializer_config_key, :context, :context_key, :cache_ids) do
5
+
6
+ def type
7
+ resource_klass._type
8
+ end
9
+
10
+ def keys
11
+ cache_ids.map do |(id, cache_key)|
12
+ [type, id, cache_key, serializer_config_key, context_key]
13
+ end
14
+ end
15
+ end
16
+
17
+ Write = Struct.new(:resource_klass, :resource, :serializer, :serializer_config_key, :context, :context_key, :relationship_data) do
18
+ def to_key_value
19
+
20
+ (id, cache_key) = resource.cache_id
21
+
22
+ json = serializer.object_hash(resource, relationship_data)
23
+
24
+ cr = CachedResponseFragment.new(
25
+ resource_klass,
26
+ id,
27
+ json['type'],
28
+ context,
29
+ resource.fetchable_fields,
30
+ json['relationships'],
31
+ json['links'],
32
+ json['attributes'],
33
+ json['meta']
34
+ )
35
+
36
+ key = [resource_klass._type, id, cache_key, serializer_config_key, context_key]
37
+
38
+ [key, cr]
39
+ end
40
+ end
41
+
42
+ attr_reader :resource_klass, :id, :type, :context, :fetchable_fields, :relationships,
43
+ :links_json, :attributes_json, :meta_json
44
+
45
+ def initialize(resource_klass, id, type, context, fetchable_fields, relationships,
46
+ links_json, attributes_json, meta_json)
47
+ @resource_klass = resource_klass
48
+ @id = id
49
+ @type = type
50
+ @context = context
51
+ @fetchable_fields = Set.new(fetchable_fields)
52
+
53
+ # Relationships left uncompiled because we'll often want to insert included ids on retrieval
54
+ # Remove the data since that should not be cached
55
+ @relationships = relationships&.transform_values {|v| v.delete_if {|k, _v| k == 'data'} }
56
+ @links_json = CompiledJson.of(links_json)
57
+ @attributes_json = CompiledJson.of(attributes_json)
58
+ @meta_json = CompiledJson.of(meta_json)
59
+ end
60
+
61
+ def to_cache_value
62
+ {
63
+ id: id,
64
+ type: type,
65
+ fetchable: fetchable_fields,
66
+ rels: relationships,
67
+ links: links_json.try(:to_s),
68
+ attrs: attributes_json.try(:to_s),
69
+ meta: meta_json.try(:to_s)
70
+ }
71
+ end
72
+
73
+ # @param [Lookup[]] lookups
74
+ # @return [Hash<Class<Resource>, Hash<ID, CachedResourceFragment>>]
75
+ def self.lookup(lookups, context)
76
+ type_to_klass = lookups.map {|l| [l.type, l.resource_klass]}.to_h
77
+
78
+ keys = lookups.map(&:keys).flatten(1)
79
+
80
+ hits = JSONAPI.configuration.resource_cache.read_multi(*keys).reject {|_, v| v.nil?}
81
+
82
+ return keys.inject({}) do |hash, key|
83
+ (type, id, _, _) = key
84
+ resource_klass = type_to_klass[type]
85
+ hash[resource_klass] ||= {}
86
+
87
+ if hits.has_key?(key)
88
+ hash[resource_klass][id] = self.from_cache_value(resource_klass, context, hits[key])
89
+ else
90
+ hash[resource_klass][id] = nil
91
+ end
92
+
93
+ hash
94
+ end
95
+ end
96
+
97
+ # @param [Write[]] lookups
98
+ def self.write(writes)
99
+ key_values = writes.map(&:to_key_value)
100
+
101
+ to_write = key_values.map {|(k, v)| [k, v.to_cache_value]}.to_h
102
+
103
+ if JSONAPI.configuration.resource_cache.respond_to? :write_multi
104
+ JSONAPI.configuration.resource_cache.write_multi(to_write)
105
+ else
106
+ to_write.each do |key, value|
107
+ JSONAPI.configuration.resource_cache.write(key, value)
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ def self.from_cache_value(resource_klass, context, h)
114
+ new(
115
+ resource_klass,
116
+ h.fetch(:id),
117
+ h.fetch(:type),
118
+ context,
119
+ h.fetch(:fetchable),
120
+ h.fetch(:rels, nil),
121
+ h.fetch(:links, nil),
122
+ h.fetch(:attrs, nil),
123
+ h.fetch(:meta, nil)
124
+ )
125
+ end
126
+ end
127
+ end
@@ -5,6 +5,7 @@ module JSONAPI
5
5
  end
6
6
 
7
7
  def self.of(obj)
8
+ # :nocov:
8
9
  case obj
9
10
  when NilClass then nil
10
11
  when CompiledJson then obj
@@ -12,6 +13,7 @@ module JSONAPI
12
13
  when Hash then CompiledJson.compile(obj)
13
14
  else raise "Can't figure out how to turn #{obj.inspect} into CompiledJson"
14
15
  end
16
+ # :nocov:
15
17
  end
16
18
 
17
19
  def initialize(json, h = nil)
@@ -19,7 +21,7 @@ module JSONAPI
19
21
  @h = h
20
22
  end
21
23
 
22
- def to_json(*args)
24
+ def to_json(*_args)
23
25
  @json
24
26
  end
25
27
 
@@ -27,9 +29,17 @@ module JSONAPI
27
29
  @json
28
30
  end
29
31
 
32
+ # :nocov:
30
33
  def to_h
31
34
  @h ||= JSON.parse(@json)
32
35
  end
36
+ # :nocov:
37
+
38
+ def [](key)
39
+ # :nocov:
40
+ to_h[key]
41
+ # :nocov:
42
+ end
33
43
 
34
44
  undef_method :as_json
35
45
  end
@@ -8,14 +8,17 @@ module JSONAPI
8
8
  :resource_key_type,
9
9
  :route_format,
10
10
  :raise_if_parameters_not_allowed,
11
+ :warn_on_route_setup_issues,
11
12
  :warn_on_missing_routes,
12
- :allow_include,
13
+ :warn_on_performance_issues,
14
+ :default_allow_include_to_one,
15
+ :default_allow_include_to_many,
13
16
  :allow_sort,
14
17
  :allow_filter,
15
18
  :default_paginator,
16
19
  :default_page_size,
17
20
  :maximum_page_size,
18
- :default_processor_klass,
21
+ :default_processor_klass_name,
19
22
  :use_text_errors,
20
23
  :top_level_links_include_pagination,
21
24
  :top_level_meta_include_record_count,
@@ -24,6 +27,7 @@ module JSONAPI
24
27
  :top_level_meta_page_count_key,
25
28
  :allow_transactions,
26
29
  :include_backtraces_in_errors,
30
+ :include_application_backtraces_in_errors,
27
31
  :exception_class_whitelist,
28
32
  :whitelist_all_exceptions,
29
33
  :always_include_to_one_linkage_data,
@@ -31,10 +35,12 @@ module JSONAPI
31
35
  :cache_formatters,
32
36
  :use_relationship_reflection,
33
37
  :resource_cache,
38
+ :default_caching,
34
39
  :default_resource_cache_field,
35
40
  :resource_cache_digest_function,
36
41
  :resource_cache_usage_report_function,
37
- :default_exclude_links
42
+ :default_exclude_links,
43
+ :use_related_resource_records_for_joins
38
44
 
39
45
  def initialize
40
46
  #:underscored_key, :camelized_key, :dasherized_key, or custom
@@ -47,13 +53,16 @@ module JSONAPI
47
53
  self.resource_key_type = :integer
48
54
 
49
55
  # optional request features
50
- self.allow_include = true
56
+ self.default_allow_include_to_one = true
57
+ self.default_allow_include_to_many = true
51
58
  self.allow_sort = true
52
59
  self.allow_filter = true
53
60
 
54
61
  self.raise_if_parameters_not_allowed = true
55
62
 
63
+ self.warn_on_route_setup_issues = true
56
64
  self.warn_on_missing_routes = true
65
+ self.warn_on_performance_issues = true
57
66
 
58
67
  # :none, :offset, :paged, or a custom paginator name
59
68
  self.default_paginator = :none
@@ -75,8 +84,12 @@ module JSONAPI
75
84
  self.use_text_errors = false
76
85
 
77
86
  # Whether or not to include exception backtraces in JSONAPI error
78
- # responses. Defaults to `false` in production, and `true` otherwise.
79
- self.include_backtraces_in_errors = !Rails.env.production?
87
+ # responses. Defaults to `false` in anything other than development or test.
88
+ self.include_backtraces_in_errors = (Rails.env.development? || Rails.env.test?)
89
+
90
+ # Whether or not to include exception application backtraces in JSONAPI error
91
+ # responses. Defaults to `false` in anything other than development or test.
92
+ self.include_application_backtraces_in_errors = (Rails.env.development? || Rails.env.test?)
80
93
 
81
94
  # List of classes that should not be rescued by the operations processor.
82
95
  # For example, if you use Pundit for authorization, you might
@@ -98,7 +111,7 @@ module JSONAPI
98
111
 
99
112
  # The default Operation Processor to use if one is not defined specifically
100
113
  # for a Resource.
101
- self.default_processor_klass = JSONAPI::Processor
114
+ self.default_processor_klass_name = 'JSONAPI::Processor'
102
115
 
103
116
  # Allows transactions for creating and updating records
104
117
  # Set this to false if your backend does not support transactions (e.g. Mongodb)
@@ -121,6 +134,11 @@ module JSONAPI
121
134
  # Rails cache store.
122
135
  self.resource_cache = nil
123
136
 
137
+ # Cache resources by default
138
+ # Cache resources by default. Individual resources can be excluded from caching by calling:
139
+ # `caching false`
140
+ self.default_caching = false
141
+
124
142
  # Default resource cache field
125
143
  # On Resources with caching enabled, this field will be used to check for out-of-date
126
144
  # cache entries, unless overridden on a specific Resource. Defaults to "updated_at".
@@ -141,6 +159,11 @@ module JSONAPI
141
159
  # and relationships. Accepts either `:default`, `:none`, or array containing the
142
160
  # specific default links to exclude, which may be `:self` and `:related`.
143
161
  self.default_exclude_links = :none
162
+
163
+ # Use a related resource's `records` when performing joins. This setting allows included resources to account for
164
+ # permission scopes. It can be overridden explicitly per relationship. Furthermore, specifying a `relation_name`
165
+ # on a relationship will cause this setting to be ignored.
166
+ self.use_related_resource_records_for_joins = true
144
167
  end
145
168
 
146
169
  def cache_formatters=(bool)
@@ -208,10 +231,26 @@ module JSONAPI
208
231
  end
209
232
 
210
233
  def default_processor_klass=(default_processor_klass)
234
+ ActiveSupport::Deprecation.warn('`default_processor_klass` has been replaced by `default_processor_klass_name`.')
211
235
  @default_processor_klass = default_processor_klass
212
236
  end
213
237
 
214
- attr_writer :allow_include, :allow_sort, :allow_filter
238
+ def default_processor_klass
239
+ @default_processor_klass ||= default_processor_klass_name.safe_constantize
240
+ end
241
+
242
+ def default_processor_klass_name=(default_processor_klass_name)
243
+ @default_processor_klass = nil
244
+ @default_processor_klass_name = default_processor_klass_name
245
+ end
246
+
247
+ def allow_include=(allow_include)
248
+ ActiveSupport::Deprecation.warn('`allow_include` has been replaced by `default_allow_include_to_one` and `default_allow_include_to_many` options.')
249
+ @default_allow_include_to_one = allow_include
250
+ @default_allow_include_to_many = allow_include
251
+ end
252
+
253
+ attr_writer :allow_sort, :allow_filter, :default_allow_include_to_one, :default_allow_include_to_many
215
254
 
216
255
  attr_writer :default_paginator
217
256
 
@@ -235,6 +274,8 @@ module JSONAPI
235
274
 
236
275
  attr_writer :include_backtraces_in_errors
237
276
 
277
+ attr_writer :include_application_backtraces_in_errors
278
+
238
279
  attr_writer :exception_class_whitelist
239
280
 
240
281
  attr_writer :whitelist_all_exceptions
@@ -245,12 +286,18 @@ module JSONAPI
245
286
 
246
287
  attr_writer :raise_if_parameters_not_allowed
247
288
 
289
+ attr_writer :warn_on_route_setup_issues
290
+
248
291
  attr_writer :warn_on_missing_routes
249
292
 
293
+ attr_writer :warn_on_performance_issues
294
+
250
295
  attr_writer :use_relationship_reflection
251
296
 
252
297
  attr_writer :resource_cache
253
298
 
299
+ attr_writer :default_caching
300
+
254
301
  attr_writer :default_resource_cache_field
255
302
 
256
303
  attr_writer :resource_cache_digest_function
@@ -258,6 +305,8 @@ module JSONAPI
258
305
  attr_writer :resource_cache_usage_report_function
259
306
 
260
307
  attr_writer :default_exclude_links
308
+
309
+ attr_writer :use_related_resource_records_for_joins
261
310
  end
262
311
 
263
312
  class << self
data/lib/jsonapi/error.rb CHANGED
@@ -24,6 +24,33 @@ module JSONAPI
24
24
  instance_variables.each {|var| hash[var.to_s.delete('@')] = instance_variable_get(var) unless instance_variable_get(var).nil? }
25
25
  hash
26
26
  end
27
+
28
+ def update_with_overrides(error_object_overrides)
29
+ @title = error_object_overrides[:title] || @title
30
+ @detail = error_object_overrides[:detail] || @detail
31
+ @id = error_object_overrides[:id] || @id
32
+ @href = error_object_overrides[:href] || href
33
+
34
+ if error_object_overrides[:code]
35
+ # :nocov:
36
+ @code = if JSONAPI.configuration.use_text_errors
37
+ TEXT_ERRORS[error_object_overrides[:code]]
38
+ else
39
+ error_object_overrides[:code]
40
+ end
41
+ # :nocov:
42
+ end
43
+
44
+ @source = error_object_overrides[:source] || @source
45
+ @links = error_object_overrides[:links] || @links
46
+
47
+ if error_object_overrides[:status]
48
+ # :nocov:
49
+ @status = Rack::Utils::SYMBOL_TO_STATUS_CODE[error_object_overrides[:status]].to_s
50
+ # :nocov:
51
+ end
52
+ @meta = error_object_overrides[:meta] || @meta
53
+ end
27
54
  end
28
55
 
29
56
  class Warning
@@ -20,6 +20,7 @@ module JSONAPI
20
20
  INVALID_FILTERS_SYNTAX = '120'
21
21
  SAVE_FAILED = '121'
22
22
  INVALID_DATA_FORMAT = '122'
23
+ INVALID_RELATIONSHIP = '123'
23
24
  BAD_REQUEST = '400'
24
25
  FORBIDDEN = '403'
25
26
  RECORD_NOT_FOUND = '404'
@@ -50,6 +51,7 @@ module JSONAPI
50
51
  INVALID_FILTERS_SYNTAX => 'INVALID_FILTERS_SYNTAX',
51
52
  SAVE_FAILED => 'SAVE_FAILED',
52
53
  INVALID_DATA_FORMAT => 'INVALID_DATA_FORMAT',
54
+ INVALID_RELATIONSHIP => 'INVALID_RELATIONSHIP',
53
55
  FORBIDDEN => 'FORBIDDEN',
54
56
  RECORD_NOT_FOUND => 'RECORD_NOT_FOUND',
55
57
  NOT_ACCEPTABLE => 'NOT_ACCEPTABLE',
@@ -1,7 +1,7 @@
1
1
  module JSONAPI
2
2
  module Exceptions
3
3
  class Error < RuntimeError
4
- attr :error_object_overrides
4
+ attr_reader :error_object_overrides
5
5
 
6
6
  def initialize(error_object_overrides = {})
7
7
  @error_object_overrides = error_object_overrides
@@ -18,6 +18,22 @@ module JSONAPI
18
18
  end
19
19
  end
20
20
 
21
+ class Errors < Error
22
+ def initialize(errors, error_object_overrides = {})
23
+ @errors = errors
24
+
25
+ @errors.each do |error|
26
+ error.update_with_overrides(error_object_overrides)
27
+ end
28
+
29
+ super(error_object_overrides)
30
+ end
31
+
32
+ def errors
33
+ @errors
34
+ end
35
+ end
36
+
21
37
  class InternalServerError < Error
22
38
  attr_accessor :exception
23
39
 
@@ -33,6 +49,12 @@ module JSONAPI
33
49
  meta[:backtrace] = exception.backtrace
34
50
  end
35
51
 
52
+ if JSONAPI.configuration.include_application_backtraces_in_errors
53
+ meta ||= Hash.new
54
+ meta[:exception] ||= exception.message
55
+ meta[:application_backtrace] = exception.backtrace.select{|line| line =~ /#{Rails.root}/}
56
+ end
57
+
36
58
  [create_error_object(code: JSONAPI::INTERNAL_SERVER_ERROR,
37
59
  status: :internal_server_error,
38
60
  title: I18n.t('jsonapi-resources.exceptions.internal_server_error.title',
@@ -119,49 +141,30 @@ module JSONAPI
119
141
  end
120
142
  end
121
143
 
122
-
123
- class HasManyRelationExists < Error
124
- attr_accessor :id
125
-
126
- def initialize(id, error_object_overrides = {})
127
- @id = id
128
- super(error_object_overrides)
129
- end
130
-
131
- def errors
132
- [create_error_object(code: JSONAPI::RELATION_EXISTS,
133
- status: :bad_request,
134
- title: I18n.translate('jsonapi-resources.exceptions.has_many_relation.title',
135
- default: 'Relation exists'),
136
- detail: I18n.translate('jsonapi-resources.exceptions.has_many_relation.detail',
137
- default: "The relation to #{id} already exists.",
138
- id: id))]
139
- end
140
- end
141
-
142
144
  class BadRequest < Error
143
- def initialize(exception)
145
+ def initialize(exception, error_object_overrides = {})
144
146
  @exception = exception
147
+ super(error_object_overrides)
145
148
  end
146
149
 
147
150
  def errors
148
- [JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST,
149
- status: :bad_request,
150
- title: I18n.translate('jsonapi-resources.exceptions.bad_request.title',
151
- default: 'Bad Request'),
152
- detail: I18n.translate('jsonapi-resources.exceptions.bad_request.detail',
153
- default: @exception))]
151
+ [create_error_object(code: JSONAPI::BAD_REQUEST,
152
+ status: :bad_request,
153
+ title: I18n.translate('jsonapi-resources.exceptions.bad_request.title',
154
+ default: 'Bad Request'),
155
+ detail: I18n.translate('jsonapi-resources.exceptions.bad_request.detail',
156
+ default: @exception))]
154
157
  end
155
158
  end
156
159
 
157
160
  class InvalidRequestFormat < Error
158
161
  def errors
159
- [JSONAPI::Error.new(code: JSONAPI::BAD_REQUEST,
160
- status: :bad_request,
161
- title: I18n.translate('jsonapi-resources.exceptions.invalid_request_format.title',
162
- default: 'Bad Request'),
163
- detail: I18n.translate('jsonapi-resources.exceptions.invalid_request_format.detail',
164
- default: 'Request must be a hash'))]
162
+ [create_error_object(code: JSONAPI::BAD_REQUEST,
163
+ status: :bad_request,
164
+ title: I18n.translate('jsonapi-resources.exceptions.invalid_request_format.title',
165
+ default: 'Bad Request'),
166
+ detail: I18n.translate('jsonapi-resources.exceptions.invalid_request_format.detail',
167
+ default: 'Request must be a hash'))]
165
168
  end
166
169
  end
167
170
 
@@ -324,6 +327,26 @@ module JSONAPI
324
327
  end
325
328
  end
326
329
 
330
+ class InvalidRelationship < Error
331
+ attr_accessor :relationship_name, :type
332
+
333
+ def initialize(type, relationship_name, error_object_overrides = {})
334
+ @relationship_name = relationship_name
335
+ @type = type
336
+ super(error_object_overrides)
337
+ end
338
+
339
+ def errors
340
+ [create_error_object(code: JSONAPI::INVALID_RELATIONSHIP,
341
+ status: :bad_request,
342
+ title: I18n.translate('jsonapi-resources.exceptions.invalid_relationship.title',
343
+ default: 'Invalid relationship'),
344
+ detail: I18n.translate('jsonapi-resources.exceptions.invalid_relationship.detail',
345
+ default: "#{relationship_name} is not a valid field for #{type}.",
346
+ relationship_name: relationship_name, type: type))]
347
+ end
348
+ end
349
+
327
350
  class InvalidInclude < Error
328
351
  attr_accessor :relationship, :resource
329
352
 
@@ -339,7 +362,7 @@ module JSONAPI
339
362
  title: I18n.translate('jsonapi-resources.exceptions.invalid_include.title',
340
363
  default: 'Invalid field'),
341
364
  detail: I18n.translate('jsonapi-resources.exceptions.invalid_include.detail',
342
- default: "#{relationship} is not a valid relationship of #{resource}",
365
+ default: "#{relationship} is not a valid includable relationship of #{resource}",
343
366
  relationship: relationship, resource: resource))]
344
367
  end
345
368
  end
@@ -374,11 +397,11 @@ module JSONAPI
374
397
 
375
398
  def errors
376
399
  [create_error_object(code: JSONAPI::PARAM_NOT_ALLOWED,
377
- status: :bad_request,
378
- title: I18n.translate('jsonapi-resources.exceptions.parameter_not_allowed.title',
379
- default: 'Param not allowed'),
380
- detail: I18n.translate('jsonapi-resources.exceptions.parameter_not_allowed.detail',
381
- default: "#{param} is not allowed.", param: param))]
400
+ status: :bad_request,
401
+ title: I18n.translate('jsonapi-resources.exceptions.parameter_not_allowed.title',
402
+ default: 'Param not allowed'),
403
+ detail: I18n.translate('jsonapi-resources.exceptions.parameters_not_allowed.detail',
404
+ default: "#{param} is not allowed.", param: param))]
382
405
  end
383
406
  end
384
407
 
@@ -108,7 +108,7 @@ end
108
108
 
109
109
  class DasherizedKeyFormatter < JSONAPI::KeyFormatter
110
110
  class << self
111
- def format(key)
111
+ def format(_key)
112
112
  super.underscore.dasherize
113
113
  end
114
114
 
@@ -146,7 +146,7 @@ end
146
146
 
147
147
  class CamelizedRouteFormatter < JSONAPI::RouteFormatter
148
148
  class << self
149
- def format(route)
149
+ def format(_route)
150
150
  super.camelize(:lower)
151
151
  end
152
152
 
@@ -158,7 +158,7 @@ end
158
158
 
159
159
  class DasherizedRouteFormatter < JSONAPI::RouteFormatter
160
160
  class << self
161
- def format(route)
161
+ def format(_route)
162
162
  super.dasherize
163
163
  end
164
164