jsonapi-resources 0.7.1.beta1 → 0.7.1.beta2
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 +248 -74
- data/lib/jsonapi-resources.rb +5 -3
- data/lib/jsonapi/acts_as_resource_controller.rb +77 -14
- data/lib/jsonapi/configuration.rb +77 -16
- data/lib/jsonapi/error.rb +12 -0
- data/lib/jsonapi/error_codes.rb +2 -0
- data/lib/jsonapi/exceptions.rb +29 -9
- data/lib/jsonapi/formatter.rb +29 -4
- data/lib/jsonapi/link_builder.rb +18 -18
- data/lib/jsonapi/mime_types.rb +25 -6
- data/lib/jsonapi/naive_cache.rb +30 -0
- data/lib/jsonapi/operation.rb +10 -342
- data/lib/jsonapi/operation_dispatcher.rb +87 -0
- data/lib/jsonapi/operation_result.rb +2 -1
- data/lib/jsonapi/paginator.rb +6 -2
- data/lib/jsonapi/processor.rb +283 -0
- data/lib/jsonapi/relationship.rb +6 -4
- data/lib/jsonapi/{request.rb → request_parser.rb} +46 -35
- data/lib/jsonapi/resource.rb +88 -13
- data/lib/jsonapi/resource_controller.rb +2 -14
- data/lib/jsonapi/resource_controller_metal.rb +17 -0
- data/lib/jsonapi/resource_serializer.rb +62 -47
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +13 -2
- data/lib/jsonapi/routing_ext.rb +49 -11
- metadata +37 -129
- data/.gitignore +0 -22
- data/.travis.yml +0 -9
- data/Gemfile +0 -23
- data/Rakefile +0 -20
- data/jsonapi-resources.gemspec +0 -29
- data/lib/jsonapi/active_record_operations_processor.rb +0 -35
- data/lib/jsonapi/operations_processor.rb +0 -120
- data/locales/en.yml +0 -80
- data/test/config/database.yml +0 -5
- data/test/controllers/controller_test.rb +0 -3312
- data/test/fixtures/active_record.rb +0 -1486
- data/test/fixtures/author_details.yml +0 -9
- data/test/fixtures/book_authors.yml +0 -3
- data/test/fixtures/book_comments.yml +0 -12
- data/test/fixtures/books.yml +0 -7
- data/test/fixtures/categories.yml +0 -35
- data/test/fixtures/comments.yml +0 -21
- data/test/fixtures/comments_tags.yml +0 -20
- data/test/fixtures/companies.yml +0 -4
- data/test/fixtures/craters.yml +0 -9
- data/test/fixtures/customers.yml +0 -11
- data/test/fixtures/documents.yml +0 -3
- data/test/fixtures/expense_entries.yml +0 -13
- data/test/fixtures/facts.yml +0 -11
- data/test/fixtures/hair_cuts.yml +0 -3
- data/test/fixtures/iso_currencies.yml +0 -17
- data/test/fixtures/line_items.yml +0 -37
- data/test/fixtures/makes.yml +0 -2
- data/test/fixtures/moons.yml +0 -6
- data/test/fixtures/numeros_telefone.yml +0 -3
- data/test/fixtures/order_flags.yml +0 -7
- data/test/fixtures/people.yml +0 -31
- data/test/fixtures/pictures.yml +0 -15
- data/test/fixtures/planet_types.yml +0 -19
- data/test/fixtures/planets.yml +0 -47
- data/test/fixtures/posts.yml +0 -102
- data/test/fixtures/posts_tags.yml +0 -59
- data/test/fixtures/preferences.yml +0 -14
- data/test/fixtures/products.yml +0 -3
- data/test/fixtures/purchase_orders.yml +0 -23
- data/test/fixtures/sections.yml +0 -8
- data/test/fixtures/tags.yml +0 -39
- data/test/fixtures/vehicles.yml +0 -17
- data/test/fixtures/web_pages.yml +0 -3
- data/test/helpers/assertions.rb +0 -13
- data/test/helpers/functional_helpers.rb +0 -59
- data/test/helpers/value_matchers.rb +0 -60
- data/test/helpers/value_matchers_test.rb +0 -40
- data/test/integration/requests/namespaced_model_test.rb +0 -13
- data/test/integration/requests/request_test.rb +0 -932
- data/test/integration/routes/routes_test.rb +0 -218
- data/test/integration/sti_fields_test.rb +0 -18
- data/test/lib/generators/jsonapi/controller_generator_test.rb +0 -25
- data/test/lib/generators/jsonapi/resource_generator_test.rb +0 -30
- data/test/test_helper.rb +0 -342
- data/test/unit/formatters/dasherized_key_formatter_test.rb +0 -8
- data/test/unit/jsonapi_request/jsonapi_request_test.rb +0 -199
- data/test/unit/operation/operations_processor_test.rb +0 -528
- data/test/unit/pagination/offset_paginator_test.rb +0 -245
- data/test/unit/pagination/paged_paginator_test.rb +0 -242
- data/test/unit/resource/resource_test.rb +0 -560
- data/test/unit/serializer/include_directives_test.rb +0 -113
- data/test/unit/serializer/link_builder_test.rb +0 -244
- data/test/unit/serializer/polymorphic_serializer_test.rb +0 -383
- data/test/unit/serializer/response_document_test.rb +0 -61
- data/test/unit/serializer/serializer_test.rb +0 -1939
data/lib/jsonapi-resources.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'jsonapi/naive_cache'
|
1
2
|
require 'jsonapi/resource'
|
2
3
|
require 'jsonapi/response_document'
|
3
4
|
require 'jsonapi/acts_as_resource_controller'
|
4
5
|
require 'jsonapi/resource_controller'
|
6
|
+
require 'jsonapi/resource_controller_metal'
|
5
7
|
require 'jsonapi/resources/version'
|
6
8
|
require 'jsonapi/configuration'
|
7
9
|
require 'jsonapi/paginator'
|
@@ -12,9 +14,9 @@ require 'jsonapi/resource_serializer'
|
|
12
14
|
require 'jsonapi/exceptions'
|
13
15
|
require 'jsonapi/error'
|
14
16
|
require 'jsonapi/error_codes'
|
15
|
-
require 'jsonapi/
|
16
|
-
require 'jsonapi/
|
17
|
-
require 'jsonapi/
|
17
|
+
require 'jsonapi/request_parser'
|
18
|
+
require 'jsonapi/operation_dispatcher'
|
19
|
+
require 'jsonapi/processor'
|
18
20
|
require 'jsonapi/relationship'
|
19
21
|
require 'jsonapi/include_directives'
|
20
22
|
require 'jsonapi/operation_result'
|
@@ -2,11 +2,16 @@ require 'csv'
|
|
2
2
|
|
3
3
|
module JSONAPI
|
4
4
|
module ActsAsResourceController
|
5
|
+
MEDIA_TYPE_MATCHER = /(.+".+"[^,]*|[^,]+)/
|
6
|
+
ALL_MEDIA_TYPES = '*/*'
|
5
7
|
|
6
8
|
def self.included(base)
|
7
9
|
base.extend ClassMethods
|
10
|
+
base.include Callbacks
|
8
11
|
base.before_action :ensure_correct_media_type, only: [:create, :update, :create_relationship, :update_relationship]
|
12
|
+
base.before_action :ensure_valid_accept_media_type
|
9
13
|
base.cattr_reader :server_error_callbacks
|
14
|
+
base.define_jsonapi_resources_callbacks :process_operations
|
10
15
|
end
|
11
16
|
|
12
17
|
def index
|
@@ -54,27 +59,44 @@ module JSONAPI
|
|
54
59
|
end
|
55
60
|
|
56
61
|
def process_request
|
57
|
-
@request = JSONAPI::
|
58
|
-
|
59
|
-
|
62
|
+
@request = JSONAPI::RequestParser.new(params, context: context,
|
63
|
+
key_formatter: key_formatter,
|
64
|
+
server_error_callbacks: (self.class.server_error_callbacks || []))
|
60
65
|
unless @request.errors.empty?
|
61
66
|
render_errors(@request.errors)
|
62
67
|
else
|
63
|
-
|
64
|
-
render_results(operation_results)
|
68
|
+
process_operations
|
69
|
+
render_results(@operation_results)
|
65
70
|
end
|
66
71
|
|
67
72
|
rescue => e
|
68
73
|
handle_exceptions(e)
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
end
|
75
|
+
|
76
|
+
def process_operations
|
77
|
+
run_callbacks :process_operations do
|
78
|
+
@operation_results = operation_dispatcher.process(@request.operations)
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
def transaction
|
83
|
+
lambda { |&block|
|
84
|
+
ActiveRecord::Base.transaction do
|
85
|
+
block.yield
|
86
|
+
end
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def rollback
|
91
|
+
lambda {
|
92
|
+
fail ActiveRecord::Rollback
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def operation_dispatcher
|
97
|
+
@operation_dispatcher ||= JSONAPI::OperationDispatcher.new(transaction: transaction,
|
98
|
+
rollback: rollback,
|
99
|
+
server_error_callbacks: @request.server_error_callbacks)
|
78
100
|
end
|
79
101
|
|
80
102
|
private
|
@@ -103,6 +125,36 @@ module JSONAPI
|
|
103
125
|
handle_exceptions(e)
|
104
126
|
end
|
105
127
|
|
128
|
+
def ensure_valid_accept_media_type
|
129
|
+
if invalid_accept_media_type?
|
130
|
+
fail JSONAPI::Exceptions::NotAcceptableError.new(request.accept)
|
131
|
+
end
|
132
|
+
rescue => e
|
133
|
+
handle_exceptions(e)
|
134
|
+
end
|
135
|
+
|
136
|
+
def invalid_accept_media_type?
|
137
|
+
media_types = media_types_for('Accept')
|
138
|
+
|
139
|
+
return false if media_types.blank? || media_types.include?(ALL_MEDIA_TYPES)
|
140
|
+
|
141
|
+
jsonapi_media_types = media_types.select do |media_type|
|
142
|
+
media_type.include?(JSONAPI::MEDIA_TYPE)
|
143
|
+
end
|
144
|
+
|
145
|
+
jsonapi_media_types.size.zero? ||
|
146
|
+
jsonapi_media_types.none? do |media_type|
|
147
|
+
media_type == JSONAPI::MEDIA_TYPE
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def media_types_for(header)
|
152
|
+
(request.headers[header] || '')
|
153
|
+
.match(MEDIA_TYPE_MATCHER)
|
154
|
+
.to_a
|
155
|
+
.map(&:strip)
|
156
|
+
end
|
157
|
+
|
106
158
|
# override to set context
|
107
159
|
def context
|
108
160
|
{}
|
@@ -117,7 +169,7 @@ module JSONAPI
|
|
117
169
|
# JSONAPI.configuration.route = :camelized_route
|
118
170
|
#
|
119
171
|
# Override if you want to set a per controller key format.
|
120
|
-
# Must return a class derived from KeyFormatter.
|
172
|
+
# Must return an instance of a class derived from KeyFormatter.
|
121
173
|
def key_formatter
|
122
174
|
JSONAPI.configuration.key_formatter
|
123
175
|
end
|
@@ -152,7 +204,18 @@ module JSONAPI
|
|
152
204
|
|
153
205
|
def render_results(operation_results)
|
154
206
|
response_doc = create_response_document(operation_results)
|
155
|
-
|
207
|
+
|
208
|
+
render_options = {
|
209
|
+
status: response_doc.status,
|
210
|
+
json: response_doc.contents,
|
211
|
+
content_type: JSONAPI::MEDIA_TYPE
|
212
|
+
}
|
213
|
+
|
214
|
+
render_options[:location] = response_doc.contents[:data]["links"][:self] if (
|
215
|
+
response_doc.status == :created && response_doc.contents[:data].class != Array
|
216
|
+
)
|
217
|
+
|
218
|
+
render(render_options)
|
156
219
|
end
|
157
220
|
|
158
221
|
def create_response_document(operation_results)
|
@@ -179,7 +242,7 @@ module JSONAPI
|
|
179
242
|
when JSONAPI::Exceptions::Error
|
180
243
|
render_errors(e.errors)
|
181
244
|
else
|
182
|
-
if JSONAPI.configuration.
|
245
|
+
if JSONAPI.configuration.exception_class_whitelisted?(e)
|
183
246
|
fail e
|
184
247
|
else
|
185
248
|
internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
|
@@ -1,29 +1,30 @@
|
|
1
1
|
require 'jsonapi/formatter'
|
2
|
-
require 'jsonapi/
|
3
|
-
require '
|
2
|
+
require 'jsonapi/processor'
|
3
|
+
require 'concurrent'
|
4
4
|
|
5
5
|
module JSONAPI
|
6
6
|
class Configuration
|
7
7
|
attr_reader :json_key_format,
|
8
8
|
:resource_key_type,
|
9
|
-
:key_formatter,
|
10
9
|
:route_format,
|
11
|
-
:route_formatter,
|
12
10
|
:raise_if_parameters_not_allowed,
|
13
|
-
:operations_processor,
|
14
11
|
:allow_include,
|
15
12
|
:allow_sort,
|
16
13
|
:allow_filter,
|
17
14
|
:default_paginator,
|
18
15
|
:default_page_size,
|
19
16
|
:maximum_page_size,
|
17
|
+
:default_processor_klass,
|
20
18
|
:use_text_errors,
|
21
19
|
:top_level_links_include_pagination,
|
22
20
|
:top_level_meta_include_record_count,
|
23
21
|
:top_level_meta_record_count_key,
|
22
|
+
:top_level_meta_include_page_count,
|
23
|
+
:top_level_meta_page_count_key,
|
24
24
|
:exception_class_whitelist,
|
25
25
|
:always_include_to_one_linkage_data,
|
26
|
-
:always_include_to_many_linkage_data
|
26
|
+
:always_include_to_many_linkage_data,
|
27
|
+
:cache_formatters
|
27
28
|
|
28
29
|
def initialize
|
29
30
|
#:underscored_key, :camelized_key, :dasherized_key, or custom
|
@@ -32,9 +33,6 @@ module JSONAPI
|
|
32
33
|
#:underscored_route, :camelized_route, :dasherized_route, or custom
|
33
34
|
self.route_format = :dasherized_route
|
34
35
|
|
35
|
-
#:basic, :active_record, or custom
|
36
|
-
self.operations_processor = :active_record
|
37
|
-
|
38
36
|
#:integer, :uuid, :string, or custom (provide a proc)
|
39
37
|
self.resource_key_type = :integer
|
40
38
|
|
@@ -59,6 +57,9 @@ module JSONAPI
|
|
59
57
|
self.top_level_meta_include_record_count = false
|
60
58
|
self.top_level_meta_record_count_key = :record_count
|
61
59
|
|
60
|
+
self.top_level_meta_include_page_count = false
|
61
|
+
self.top_level_meta_page_count_key = :page_count
|
62
|
+
|
62
63
|
self.use_text_errors = false
|
63
64
|
|
64
65
|
# List of classes that should not be rescued by the operations processor.
|
@@ -74,25 +75,81 @@ module JSONAPI
|
|
74
75
|
# NOTE: always_include_to_many_linkage_data is not currently implemented
|
75
76
|
self.always_include_to_one_linkage_data = false
|
76
77
|
self.always_include_to_many_linkage_data = false
|
78
|
+
|
79
|
+
# The default Operation Processor to use if one is not defined specifically
|
80
|
+
# for a Resource.
|
81
|
+
self.default_processor_klass = JSONAPI::Processor
|
82
|
+
|
83
|
+
# Formatter Caching
|
84
|
+
# Set to false to disable caching of string operations on keys and links.
|
85
|
+
self.cache_formatters = true
|
86
|
+
end
|
87
|
+
|
88
|
+
def cache_formatters=(bool)
|
89
|
+
@cache_formatters = bool
|
90
|
+
if bool
|
91
|
+
@key_formatter_tlv = Concurrent::ThreadLocalVar.new
|
92
|
+
@route_formatter_tlv = Concurrent::ThreadLocalVar.new
|
93
|
+
else
|
94
|
+
@key_formatter_tlv = nil
|
95
|
+
@route_formatter_tlv = nil
|
96
|
+
end
|
77
97
|
end
|
78
98
|
|
79
99
|
def json_key_format=(format)
|
80
100
|
@json_key_format = format
|
81
|
-
@
|
101
|
+
if @cache_formatters
|
102
|
+
@key_formatter_tlv = Concurrent::ThreadLocalVar.new
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def route_format=(format)
|
107
|
+
@route_format = format
|
108
|
+
if @cache_formatters
|
109
|
+
@route_formatter_tlv = Concurrent::ThreadLocalVar.new
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def key_formatter
|
114
|
+
if self.cache_formatters
|
115
|
+
formatter = @key_formatter_tlv.value
|
116
|
+
return formatter if formatter
|
117
|
+
end
|
118
|
+
|
119
|
+
formatter = JSONAPI::Formatter.formatter_for(self.json_key_format)
|
120
|
+
|
121
|
+
if self.cache_formatters
|
122
|
+
formatter = @key_formatter_tlv.value = formatter.cached
|
123
|
+
end
|
124
|
+
|
125
|
+
return formatter
|
82
126
|
end
|
83
127
|
|
84
128
|
def resource_key_type=(key_type)
|
85
129
|
@resource_key_type = key_type
|
86
130
|
end
|
87
131
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
132
|
+
def route_formatter
|
133
|
+
if self.cache_formatters
|
134
|
+
formatter = @route_formatter_tlv.value
|
135
|
+
return formatter if formatter
|
136
|
+
end
|
137
|
+
|
138
|
+
formatter = JSONAPI::Formatter.formatter_for(self.route_format)
|
139
|
+
|
140
|
+
if self.cache_formatters
|
141
|
+
formatter = @route_formatter_tlv.value = formatter.cached
|
142
|
+
end
|
143
|
+
|
144
|
+
return formatter
|
145
|
+
end
|
146
|
+
|
147
|
+
def exception_class_whitelisted?(e)
|
148
|
+
@exception_class_whitelist.flatten.any? { |k| e.class.ancestors.include?(k) }
|
91
149
|
end
|
92
150
|
|
93
|
-
def
|
94
|
-
@
|
95
|
-
@operations_processor = JSONAPI::OperationsProcessor.operations_processor_for(@operations_processor_name)
|
151
|
+
def default_processor_klass=(default_processor_klass)
|
152
|
+
@default_processor_klass = default_processor_klass
|
96
153
|
end
|
97
154
|
|
98
155
|
attr_writer :allow_include, :allow_sort, :allow_filter
|
@@ -111,6 +168,10 @@ module JSONAPI
|
|
111
168
|
|
112
169
|
attr_writer :top_level_meta_record_count_key
|
113
170
|
|
171
|
+
attr_writer :top_level_meta_include_page_count
|
172
|
+
|
173
|
+
attr_writer :top_level_meta_page_count_key
|
174
|
+
|
114
175
|
attr_writer :exception_class_whitelist
|
115
176
|
|
116
177
|
attr_writer :always_include_to_one_linkage_data
|
data/lib/jsonapi/error.rb
CHANGED
@@ -18,6 +18,12 @@ module JSONAPI
|
|
18
18
|
@status = Rack::Utils::SYMBOL_TO_STATUS_CODE[options[:status]].to_s
|
19
19
|
@meta = options[:meta]
|
20
20
|
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
hash = {}
|
24
|
+
instance_variables.each {|var| hash[var.to_s.delete('@')] = instance_variable_get(var) unless instance_variable_get(var).nil? }
|
25
|
+
hash
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
29
|
class Warning
|
@@ -31,5 +37,11 @@ module JSONAPI
|
|
31
37
|
options[:code]
|
32
38
|
end
|
33
39
|
end
|
40
|
+
|
41
|
+
def to_hash
|
42
|
+
hash = {}
|
43
|
+
instance_variables.each {|var| hash[var.to_s.delete('@')] = instance_variable_get(var) unless instance_variable_get(var).nil? }
|
44
|
+
hash
|
45
|
+
end
|
34
46
|
end
|
35
47
|
end
|
data/lib/jsonapi/error_codes.rb
CHANGED
@@ -22,6 +22,7 @@ module JSONAPI
|
|
22
22
|
SAVE_FAILED = '121'
|
23
23
|
FORBIDDEN = '403'
|
24
24
|
RECORD_NOT_FOUND = '404'
|
25
|
+
NOT_ACCEPTABLE = '406'
|
25
26
|
UNSUPPORTED_MEDIA_TYPE = '415'
|
26
27
|
LOCKED = '423'
|
27
28
|
INTERNAL_SERVER_ERROR = '500'
|
@@ -50,6 +51,7 @@ module JSONAPI
|
|
50
51
|
SAVE_FAILED => 'SAVE_FAILED',
|
51
52
|
FORBIDDEN => 'FORBIDDEN',
|
52
53
|
RECORD_NOT_FOUND => 'RECORD_NOT_FOUND',
|
54
|
+
NOT_ACCEPTABLE => 'NOT_ACCEPTABLE',
|
53
55
|
UNSUPPORTED_MEDIA_TYPE => 'UNSUPPORTED_MEDIA_TYPE',
|
54
56
|
LOCKED => 'LOCKED',
|
55
57
|
INTERNAL_SERVER_ERROR => 'INTERNAL_SERVER_ERROR'
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -18,9 +18,9 @@ module JSONAPI
|
|
18
18
|
|
19
19
|
[JSONAPI::Error.new(code: JSONAPI::INTERNAL_SERVER_ERROR,
|
20
20
|
status: :internal_server_error,
|
21
|
-
title: I18n.t('jsonapi-resources.exceptions.internal_server_error.title',
|
21
|
+
title: I18n.t('jsonapi-resources.exceptions.internal_server_error.title',
|
22
22
|
default: 'Internal Server Error'),
|
23
|
-
detail: I18n.t('jsonapi-resources.exceptions.internal_server_error.detail',
|
23
|
+
detail: I18n.t('jsonapi-resources.exceptions.internal_server_error.detail',
|
24
24
|
default: 'Internal Server Error'),
|
25
25
|
meta: meta)]
|
26
26
|
end
|
@@ -35,9 +35,9 @@ module JSONAPI
|
|
35
35
|
def errors
|
36
36
|
[JSONAPI::Error.new(code: JSONAPI::INVALID_RESOURCE,
|
37
37
|
status: :bad_request,
|
38
|
-
title: I18n.t('jsonapi-resources.exceptions.invalid_resource.title',
|
38
|
+
title: I18n.t('jsonapi-resources.exceptions.invalid_resource.title',
|
39
39
|
default: 'Invalid resource'),
|
40
|
-
detail: I18n.t('jsonapi-resources.exceptions.invalid_resource.detail',
|
40
|
+
detail: I18n.t('jsonapi-resources.exceptions.invalid_resource.detail',
|
41
41
|
default: "#{resource} is not a valid resource.", resource: resource))]
|
42
42
|
end
|
43
43
|
end
|
@@ -51,9 +51,9 @@ module JSONAPI
|
|
51
51
|
def errors
|
52
52
|
[JSONAPI::Error.new(code: JSONAPI::RECORD_NOT_FOUND,
|
53
53
|
status: :not_found,
|
54
|
-
title: I18n.translate('jsonapi-resources.exceptions.record_not_found.title',
|
54
|
+
title: I18n.translate('jsonapi-resources.exceptions.record_not_found.title',
|
55
55
|
default: 'Record not found'),
|
56
|
-
detail: I18n.translate('jsonapi-resources.exceptions.record_not_found.detail',
|
56
|
+
detail: I18n.translate('jsonapi-resources.exceptions.record_not_found.detail',
|
57
57
|
default: "The record identified by #{id} could not be found.", id: id))]
|
58
58
|
end
|
59
59
|
end
|
@@ -67,7 +67,7 @@ module JSONAPI
|
|
67
67
|
def errors
|
68
68
|
[JSONAPI::Error.new(code: JSONAPI::UNSUPPORTED_MEDIA_TYPE,
|
69
69
|
status: :unsupported_media_type,
|
70
|
-
title: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.title',
|
70
|
+
title: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.title',
|
71
71
|
default: 'Unsupported media type'),
|
72
72
|
detail: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.detail',
|
73
73
|
default: "All requests that create or update must use the '#{JSONAPI::MEDIA_TYPE}' Content-Type. This request specified '#{media_type}'.",
|
@@ -76,6 +76,26 @@ module JSONAPI
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
class NotAcceptableError < Error
|
80
|
+
attr_accessor :media_type
|
81
|
+
|
82
|
+
def initialize(media_type)
|
83
|
+
@media_type = media_type
|
84
|
+
end
|
85
|
+
|
86
|
+
def errors
|
87
|
+
[JSONAPI::Error.new(code: JSONAPI::NOT_ACCEPTABLE,
|
88
|
+
status: :not_acceptable,
|
89
|
+
title: I18n.translate('jsonapi-resources.exceptions.not_acceptable.title',
|
90
|
+
default: 'Not acceptable'),
|
91
|
+
detail: I18n.translate('jsonapi-resources.exceptions.not_acceptable.detail',
|
92
|
+
default: "All requests must use the '#{JSONAPI::MEDIA_TYPE}' Accept without media type parameters. This request specified '#{media_type}'.",
|
93
|
+
needed_media_type: JSONAPI::MEDIA_TYPE,
|
94
|
+
media_type: media_type))]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
79
99
|
class HasManyRelationExists < Error
|
80
100
|
attr_accessor :id
|
81
101
|
def initialize(id)
|
@@ -85,7 +105,7 @@ module JSONAPI
|
|
85
105
|
def errors
|
86
106
|
[JSONAPI::Error.new(code: JSONAPI::RELATION_EXISTS,
|
87
107
|
status: :bad_request,
|
88
|
-
title: I18n.translate('jsonapi-resources.exceptions.has_many_relation.title',
|
108
|
+
title: I18n.translate('jsonapi-resources.exceptions.has_many_relation.title',
|
89
109
|
default: 'Relation exists'),
|
90
110
|
detail: I18n.translate('jsonapi-resources.exceptions.has_many_relation.detail',
|
91
111
|
default: "The relation to #{id} already exists.",
|
@@ -97,7 +117,7 @@ module JSONAPI
|
|
97
117
|
def errors
|
98
118
|
[JSONAPI::Error.new(code: JSONAPI::FORBIDDEN,
|
99
119
|
status: :forbidden,
|
100
|
-
title: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.title',
|
120
|
+
title: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.title',
|
101
121
|
default: 'Complete replacement forbidden'),
|
102
122
|
detail: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.detail',
|
103
123
|
default: 'Complete replacement forbidden for this relationship'))]
|