jsonapi-resources 0.9.12 → 0.10.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +34 -11
- data/lib/bug_report_templates/rails_5_latest.rb +125 -0
- data/lib/bug_report_templates/rails_5_master.rb +140 -0
- data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +27 -0
- data/lib/jsonapi/active_relation/join_manager.rb +303 -0
- data/lib/jsonapi/active_relation_resource.rb +884 -0
- data/lib/jsonapi/acts_as_resource_controller.rb +122 -106
- data/lib/jsonapi/basic_resource.rb +1162 -0
- data/lib/jsonapi/cached_response_fragment.rb +127 -0
- data/lib/jsonapi/compiled_json.rb +11 -1
- data/lib/jsonapi/configuration.rb +57 -8
- data/lib/jsonapi/error.rb +27 -0
- data/lib/jsonapi/error_codes.rb +2 -0
- data/lib/jsonapi/exceptions.rb +63 -40
- data/lib/jsonapi/formatter.rb +3 -3
- data/lib/jsonapi/include_directives.rb +18 -75
- data/lib/jsonapi/link_builder.rb +18 -25
- data/lib/jsonapi/operation.rb +16 -5
- data/lib/jsonapi/operation_result.rb +73 -15
- data/lib/jsonapi/paginator.rb +17 -0
- data/lib/jsonapi/path.rb +43 -0
- data/lib/jsonapi/path_segment.rb +76 -0
- data/lib/jsonapi/processor.rb +246 -111
- data/lib/jsonapi/relationship.rb +117 -24
- data/lib/jsonapi/request_parser.rb +383 -396
- data/lib/jsonapi/resource.rb +3 -1376
- data/lib/jsonapi/resource_controller_metal.rb +3 -0
- data/lib/jsonapi/resource_fragment.rb +47 -0
- data/lib/jsonapi/resource_id_tree.rb +112 -0
- data/lib/jsonapi/resource_identity.rb +42 -0
- data/lib/jsonapi/resource_serializer.rb +124 -286
- data/lib/jsonapi/resource_set.rb +176 -0
- data/lib/jsonapi/resources/railtie.rb +9 -0
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +104 -87
- data/lib/jsonapi/routing_ext.rb +19 -21
- data/lib/jsonapi-resources.rb +20 -4
- data/lib/tasks/check_upgrade.rake +52 -0
- metadata +34 -31
- data/lib/jsonapi/cached_resource_fragment.rb +0 -127
- data/lib/jsonapi/operation_dispatcher.rb +0 -88
- data/lib/jsonapi/operation_results.rb +0 -35
- 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(*
|
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
|
-
:
|
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
|
-
:
|
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.
|
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
|
79
|
-
self.include_backtraces_in_errors =
|
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.
|
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
|
-
|
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
|
data/lib/jsonapi/error_codes.rb
CHANGED
@@ -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',
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
module Exceptions
|
3
3
|
class Error < RuntimeError
|
4
|
-
|
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
|
-
[
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
[
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
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
|
|
data/lib/jsonapi/formatter.rb
CHANGED
@@ -108,7 +108,7 @@ end
|
|
108
108
|
|
109
109
|
class DasherizedKeyFormatter < JSONAPI::KeyFormatter
|
110
110
|
class << self
|
111
|
-
def format(
|
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(
|
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(
|
161
|
+
def format(_route)
|
162
162
|
super.dasherize
|
163
163
|
end
|
164
164
|
|