api_error_handler 0.1.0.rc → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +14 -2
- data/.rubocop.yml +30 -0
- data/.rubocop_todo.yml +85 -0
- data/.ruby-version +1 -0
- data/.travis.yml +33 -4
- data/Gemfile +2 -0
- data/README.md +289 -12
- data/Rakefile +3 -1
- data/api_error_handler.gemspec +24 -10
- data/bin/console +1 -0
- data/lib/api_error_handler/action_controller.rb +6 -4
- data/lib/api_error_handler/error_id_generator.rb +23 -0
- data/lib/api_error_handler/error_reporter.rb +51 -0
- data/lib/api_error_handler/errors.rb +8 -0
- data/lib/api_error_handler/serializers/base_serializer.rb +24 -0
- data/lib/api_error_handler/serializers/json.rb +29 -1
- data/lib/api_error_handler/serializers/json_api.rb +30 -0
- data/lib/api_error_handler/serializers/xml.rb +26 -0
- data/lib/api_error_handler/version.rb +3 -1
- data/lib/api_error_handler.rb +49 -5
- metadata +59 -25
- data/Gemfile.lock +0 -96
- data/lib/api_error_handler/error_serializer.rb +0 -25
- data/lib/serializers/json.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 18b6ef31f241b4845ddbf59be8721e55a218a84fb4d39fad730b2c6941e616fe
|
4
|
+
data.tar.gz: 9881362b337b651e73c2472996f6e4c959660bec85fe9856d7a8c54f2b4206e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4c5ed604f7295e4b1e54738aafd43d3288ce98a8f93b5e18897077f4691b713b08db3db1d1cb06c988ec62aae5f51f02aa8d4bfed3ed795e89de9cf360ed2fd
|
7
|
+
data.tar.gz: 8cc44416b4ecadc12b17ab728f1ce30e067d53582fae1b2891e6a5b7a6acacab2ed12be1e33ed93250f2bdd7110e5becc76069f36698b74f8ee1571fef53c06c
|
data/.gitignore
CHANGED
@@ -7,8 +7,20 @@
|
|
7
7
|
/spec/reports/
|
8
8
|
/tmp/
|
9
9
|
|
10
|
+
/Gemfile.lock
|
11
|
+
|
10
12
|
# rspec failure tracking
|
11
13
|
.rspec_status
|
12
14
|
|
13
|
-
# Stuff to ignore in the
|
14
|
-
|
15
|
+
# Stuff to ignore in the test_apps
|
16
|
+
rails_5_test_app/tmp
|
17
|
+
rails_5_test_app/log
|
18
|
+
rails_5_test_app/.byebug_history
|
19
|
+
|
20
|
+
rails_4_test_app/tmp
|
21
|
+
rails_4_test_app/log
|
22
|
+
rails_4_test_app/.byebug_history
|
23
|
+
|
24
|
+
rails_6_test_app/tmp
|
25
|
+
rails_6_test_app/log
|
26
|
+
rails_6_test_app/.byebug_history
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.5
|
5
|
+
Exclude:
|
6
|
+
- 'vendor/**/*'
|
7
|
+
- 'rails_*/**/*'
|
8
|
+
|
9
|
+
Style/StringLiterals:
|
10
|
+
EnforcedStyle: double_quotes
|
11
|
+
|
12
|
+
Metrics/LineLength:
|
13
|
+
Max: 100
|
14
|
+
|
15
|
+
Style/MethodCallWithoutArgsParentheses:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Style/TrailingCommaInArrayLiteral:
|
19
|
+
EnforcedStyleForMultiline: comma
|
20
|
+
|
21
|
+
Style/TrailingCommaInHashLiteral:
|
22
|
+
EnforcedStyleForMultiline: comma
|
23
|
+
|
24
|
+
Metrics/BlockLength:
|
25
|
+
Exclude:
|
26
|
+
- 'spec/**/*.rb'
|
27
|
+
- 'api_error_handler.gemspec'
|
28
|
+
|
29
|
+
Style/Documentation:
|
30
|
+
Enabled: false
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 100`
|
3
|
+
# on 2019-08-25 13:23:25 +0100 using RuboCop version 0.74.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Cop supports --auto-correct.
|
11
|
+
# Configuration parameters: TreatCommentsAsGroupSeparators, Include.
|
12
|
+
# Include: **/*.gemspec
|
13
|
+
Gemspec/OrderedDependencies:
|
14
|
+
Exclude:
|
15
|
+
- 'api_error_handler.gemspec'
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Cop supports --auto-correct.
|
19
|
+
Layout/ClosingParenthesisIndentation:
|
20
|
+
Exclude:
|
21
|
+
- 'spec/api_error_handler/serializers/xml_spec.rb'
|
22
|
+
|
23
|
+
# Offense count: 2
|
24
|
+
# Configuration parameters: Max.
|
25
|
+
Metrics/AbcSize:
|
26
|
+
Exclude:
|
27
|
+
- 'lib/api_error_handler.rb'
|
28
|
+
- 'lib/api_error_handler/error_reporter.rb'
|
29
|
+
|
30
|
+
# Offense count: 1
|
31
|
+
# Configuration parameters: Max.
|
32
|
+
Metrics/CyclomaticComplexity:
|
33
|
+
Exclude:
|
34
|
+
- 'lib/api_error_handler/error_reporter.rb'
|
35
|
+
|
36
|
+
# Offense count: 3
|
37
|
+
# Configuration parameters: CountComments, Max, ExcludedMethods.
|
38
|
+
Metrics/MethodLength:
|
39
|
+
Exclude:
|
40
|
+
- 'lib/api_error_handler.rb'
|
41
|
+
- 'lib/api_error_handler/error_reporter.rb'
|
42
|
+
- 'lib/api_error_handler/error_id_generator.rb'
|
43
|
+
- 'lib/api_error_handler/serializers/json_api.rb'
|
44
|
+
|
45
|
+
# Offense count: 1
|
46
|
+
# Configuration parameters: Max.
|
47
|
+
Metrics/PerceivedComplexity:
|
48
|
+
Exclude:
|
49
|
+
- 'lib/api_error_handler/error_reporter.rb'
|
50
|
+
|
51
|
+
# Offense count: 2
|
52
|
+
# Cop supports --auto-correct.
|
53
|
+
Style/ExpandPathArguments:
|
54
|
+
Exclude:
|
55
|
+
- 'api_error_handler.gemspec'
|
56
|
+
|
57
|
+
# Offense count: 4
|
58
|
+
# Cop supports --auto-correct.
|
59
|
+
# Configuration parameters: EnforcedStyle.
|
60
|
+
# SupportedStyles: implicit, explicit
|
61
|
+
Style/RescueStandardError:
|
62
|
+
Exclude:
|
63
|
+
- 'lib/api_error_handler.rb'
|
64
|
+
- 'spec/api_error_handler/serializers/json_api_spec.rb'
|
65
|
+
- 'spec/api_error_handler/serializers/json_spec.rb'
|
66
|
+
- 'spec/api_error_handler/serializers/xml_spec.rb'
|
67
|
+
|
68
|
+
# Offense count: 2
|
69
|
+
# Cop supports --auto-correct.
|
70
|
+
# Configuration parameters: EnforcedStyleForMultiline.
|
71
|
+
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
72
|
+
Style/TrailingCommaInArrayLiteral:
|
73
|
+
Exclude:
|
74
|
+
- 'lib/api_error_handler/serializers/json_api.rb'
|
75
|
+
- 'spec/api_error_handler/serializers/json_api_spec.rb'
|
76
|
+
|
77
|
+
# Offense count: 3
|
78
|
+
# Cop supports --auto-correct.
|
79
|
+
# Configuration parameters: EnforcedStyleForMultiline.
|
80
|
+
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
81
|
+
Style/TrailingCommaInHashLiteral:
|
82
|
+
Exclude:
|
83
|
+
- 'lib/api_error_handler.rb'
|
84
|
+
- 'lib/api_error_handler/serializers/json.rb'
|
85
|
+
- 'lib/api_error_handler/serializers/json_api.rb'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.8
|
data/.travis.yml
CHANGED
@@ -1,7 +1,36 @@
|
|
1
1
|
---
|
2
|
-
sudo: false
|
3
2
|
language: ruby
|
3
|
+
before_install:
|
4
|
+
- gem update --system
|
5
|
+
- gem install bundler
|
6
|
+
install: bundle install --jobs=3 --retry=3
|
4
7
|
cache: bundler
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
branches:
|
9
|
+
only:
|
10
|
+
- master
|
11
|
+
jobs:
|
12
|
+
include:
|
13
|
+
- rvm: 2.5.1
|
14
|
+
gemfile: ./rails_5_test_app/Gemfile
|
15
|
+
script: cd rails_5_test_app && bundle exec rspec
|
16
|
+
- rvm: 2.5.1
|
17
|
+
gemfile: ./rails_6_test_app/Gemfile
|
18
|
+
script: cd rails_6_test_app && bundle exec rspec
|
19
|
+
- rvm: 2.7.2
|
20
|
+
gemfile: ./rails_6_test_app/Gemfile
|
21
|
+
script: cd rails_6_test_app && bundle exec rspec
|
22
|
+
- rvm: 3.0.0
|
23
|
+
gemfile: ./rails_6_test_app/Gemfile
|
24
|
+
script: cd rails_6_test_app && bundle exec rspec
|
25
|
+
- rvm: 2.7.2
|
26
|
+
gemfile: Gemfile
|
27
|
+
script: bundle exec rubocop
|
28
|
+
- rvm: 2.7.2
|
29
|
+
gemfile: Gemfile
|
30
|
+
script: bundle exec rspec
|
31
|
+
- rvm: 3.0.0
|
32
|
+
gemfile: Gemfile
|
33
|
+
script: bundle exec rubocop
|
34
|
+
- rvm: 3.0.0
|
35
|
+
gemfile: Gemfile
|
36
|
+
script: bundle exec rspec
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,26 @@
|
|
1
1
|
# ApiErrorHandler
|
2
|
+
[![Build Status](https://travis-ci.org/jamesstonehill/api_error_handler.svg?branch=master)](https://travis-ci.org/jamesstonehill/api_error_handler)
|
2
3
|
|
3
|
-
|
4
|
+
Are your API error responses not all that you want them to be? If so, you've
|
5
|
+
found the right gem! `api_error_handler` handles all aspects of returning
|
6
|
+
informative, spec-compliant responses to clients when your application
|
7
|
+
encounters an error in the course of processing a response.
|
4
8
|
|
5
|
-
|
9
|
+
This "handling" includes:
|
10
|
+
- __Error serialization__: each response will include a response body that
|
11
|
+
gives some information on the type of error that your application
|
12
|
+
encountered. See the [Responses Body Options](#response-body-options)
|
13
|
+
section for details and configuration options.
|
14
|
+
- __Status code setting__: `api_error_handler` will set the HTTP status code of
|
15
|
+
the response based on the type of error that is raised. For example, when an
|
16
|
+
`ActiveRecord::RecordNotFound` error is raised, it will set the response
|
17
|
+
status to 404. See the [HTTP Status Mapping](#http-status-mapping) section
|
18
|
+
for details and configuration options.
|
19
|
+
- __Error reporting__: If you use a 3rd party bug tracking
|
20
|
+
tool like Honeybadger or Sentry, `api_error_handler` will notify this
|
21
|
+
service of the error for you so you don't have to!
|
22
|
+
- __Content type setting__: `api_error_handler` will set the content type of the
|
23
|
+
response based on the format of response body.
|
6
24
|
|
7
25
|
## Installation
|
8
26
|
|
@@ -14,25 +32,284 @@ gem 'api_error_handler'
|
|
14
32
|
|
15
33
|
And then execute:
|
16
34
|
|
17
|
-
$ bundle
|
35
|
+
$ bundle install
|
18
36
|
|
19
|
-
|
37
|
+
## Usage
|
20
38
|
|
21
|
-
|
39
|
+
To get started, all you need to do is invoke `handle_api_errors` inside your
|
40
|
+
controller like so:
|
22
41
|
|
23
|
-
|
42
|
+
```ruby
|
43
|
+
class MyController < ActionController::API
|
44
|
+
handle_api_errors()
|
45
|
+
|
46
|
+
def index
|
47
|
+
raise "Something is very very wrong!"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Now when you go to `MyController#index`, your API will return the following
|
53
|
+
response:
|
54
|
+
|
55
|
+
```json
|
56
|
+
HTTP/1.1 500 Internal Server Error
|
57
|
+
Content-Type: application/json
|
58
|
+
|
59
|
+
{
|
60
|
+
"error": {
|
61
|
+
"title":"Internal Server Error",
|
62
|
+
"detail":"Something is very very wrong!"
|
63
|
+
}
|
64
|
+
}
|
65
|
+
```
|
66
|
+
|
67
|
+
### Error handling options
|
68
|
+
|
69
|
+
`handle_api_errors` implements a bunch of (hopefully) sensible defaults so that
|
70
|
+
all you need to do is invoke `handle_api_errors()` in your controller to get
|
71
|
+
useful error handling! However, in all likelihood you'll want to override some
|
72
|
+
of these options. This section gives details on the various options available
|
73
|
+
for configuring the `api_error_handler`.
|
74
|
+
|
75
|
+
#### Response Body Options
|
76
|
+
By default, `handle_api_errors` picks the `:json` format for serializing errors.
|
77
|
+
However, this gem comes with a number of other formats for serializing your
|
78
|
+
errors.
|
79
|
+
|
80
|
+
##### JSON (the default)
|
81
|
+
```ruby
|
82
|
+
handle_api_errors(format: :json)
|
83
|
+
# Or
|
84
|
+
handle_api_errors()
|
85
|
+
```
|
86
|
+
|
87
|
+
```json
|
88
|
+
HTTP/1.1 500 Internal Server Error
|
89
|
+
Content-Type: application/json
|
90
|
+
|
91
|
+
{
|
92
|
+
"error": {
|
93
|
+
"title":"Internal Server Error",
|
94
|
+
"detail":"Something is very very wrong!"
|
95
|
+
}
|
96
|
+
}
|
97
|
+
```
|
98
|
+
|
99
|
+
##### JSON:API
|
100
|
+
If your API follows the `JSON:API` spec, you'll want to use the `:json_api`
|
101
|
+
format option.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
handle_api_errors(format: :json_api)
|
105
|
+
```
|
106
|
+
|
107
|
+
Responses with this format will follow the `JSON:API` [specification for error
|
108
|
+
objects](https://jsonapi.org/format/#error-objects). This will look something
|
109
|
+
like this:
|
110
|
+
|
111
|
+
```json
|
112
|
+
HTTP/1.1 500 Internal Server Error
|
113
|
+
Content-Type: application/vnd.api+json
|
114
|
+
|
115
|
+
{
|
116
|
+
"errors": [
|
117
|
+
{
|
118
|
+
"status":"500",
|
119
|
+
"title":"Internal Server Error",
|
120
|
+
"detail":"Something is very very wrong!"
|
121
|
+
}
|
122
|
+
]
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
126
|
+
##### XML
|
127
|
+
```ruby
|
128
|
+
handle_api_errors(format: :xml)
|
129
|
+
```
|
130
|
+
|
131
|
+
```xml
|
132
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
133
|
+
<Error>
|
134
|
+
<Title>Internal Server Error</title>
|
135
|
+
<Detail>Something is very very wrong!</detail>
|
136
|
+
</Error>
|
137
|
+
```
|
138
|
+
|
139
|
+
##### Custom Error Responses
|
140
|
+
If none of the out-of-the-box options suit you then you can pass in your own
|
141
|
+
error serializer like so:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
handle_api_errors(serializer: MyCustomErrorSerializer)
|
145
|
+
```
|
146
|
+
|
147
|
+
The custom serializer must implement two instance methods, `serialize` and
|
148
|
+
`render_format`. The `serialize` method should return the body of the response
|
149
|
+
you want to render. The `render_format` should be the format that you want to
|
150
|
+
render the response in (e.g `:json`, `:xml`, `:plain`), which will be passed to
|
151
|
+
Rails' `render` method.
|
152
|
+
|
153
|
+
It is recommended you inherit your serializer from
|
154
|
+
`ApiErrorHandler::Serializers::BaseSerializer` to gain some helpful instance
|
155
|
+
methods and defaults.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
class MyCustomErrorSerializer < ApiErrorHandler::Serializers::BaseSerializer
|
159
|
+
def serialize(serializer_options)
|
160
|
+
# The `title` and `status_code` come from the BaseSerializer.
|
161
|
+
"Error! Title: #{title} Status Code: #{status_code}"
|
162
|
+
end
|
24
163
|
|
25
|
-
|
164
|
+
def render_format
|
165
|
+
:plain
|
166
|
+
end
|
167
|
+
end
|
168
|
+
```
|
169
|
+
##### Backtraces
|
170
|
+
If you want to include the error's backtrace in the response body:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
handle_api_errors(backtrace: true)
|
174
|
+
```
|
175
|
+
|
176
|
+
```json
|
177
|
+
{
|
178
|
+
"error": {
|
179
|
+
"title":"Internal Server Error",
|
180
|
+
"detail":"Something is very very wrong!",
|
181
|
+
"backtrace": [
|
182
|
+
# The backtrace
|
183
|
+
]
|
184
|
+
}
|
185
|
+
}
|
186
|
+
```
|
187
|
+
|
188
|
+
### HTTP Status Mapping
|
189
|
+
|
190
|
+
Most of the time, you'll want to set the HTTP status code based on the type of
|
191
|
+
error being raised. To determine which errors map to which status codes,
|
192
|
+
`api_error_handler` uses `ActionDispatch::ExceptionWrapper.rescue_responses`. If
|
193
|
+
you're using Rails with ActiveRecord, by default this includes:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
{
|
197
|
+
"ActionController::RoutingError" => :not_found,
|
198
|
+
"AbstractController::ActionNotFound" => :not_found,
|
199
|
+
"ActionController::MethodNotAllowed" => :method_not_allowed,
|
200
|
+
"ActionController::UnknownHttpMethod" => :method_not_allowed,
|
201
|
+
"ActionController::NotImplemented" => :not_implemented,
|
202
|
+
"ActionController::UnknownFormat" => :not_acceptable,
|
203
|
+
"Mime::Type::InvalidMimeType" => :not_acceptable,
|
204
|
+
"ActionController::MissingExactTemplate" => :not_acceptable,
|
205
|
+
"ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
|
206
|
+
"ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
|
207
|
+
"ActionDispatch::Http::Parameters::ParseError" => :bad_request,
|
208
|
+
"ActionController::BadRequest" => :bad_request,
|
209
|
+
"ActionController::ParameterMissing" => :bad_request,
|
210
|
+
"Rack::QueryParser::ParameterTypeError" => :bad_request,
|
211
|
+
"Rack::QueryParser::InvalidParameterError" => :bad_request,
|
212
|
+
"ActiveRecord::RecordNotFound" => :not_found,
|
213
|
+
"ActiveRecord::StaleObjectError" => :conflict,
|
214
|
+
"ActiveRecord::RecordInvalid" => :unprocessable_entity,
|
215
|
+
"ActiveRecord::RecordNotSaved" => :unprocessable_entity
|
216
|
+
}
|
217
|
+
```
|
218
|
+
- https://guides.rubyonrails.org/configuring.html#configuring-action-dispatch
|
219
|
+
|
220
|
+
You can add to this mapping on an application level by doing the following:
|
221
|
+
```ruby
|
222
|
+
config.action_dispatch.rescue_responses.merge!(
|
223
|
+
"AuthenticationError" => :unauthorized
|
224
|
+
)
|
225
|
+
```
|
226
|
+
|
227
|
+
Now when an you raise an `AuthenticationError` in one of your actions, the
|
228
|
+
status code of the response will be 401.
|
26
229
|
|
27
|
-
|
230
|
+
### Error IDs
|
231
|
+
Sometimes it's helpful to include IDs with your error responses so that you can
|
232
|
+
correlate a specific error with a record in your logs or bug tracking software.
|
233
|
+
For this you can use the `error_id` option.
|
28
234
|
|
29
|
-
|
235
|
+
You can either use the UUID error strategy
|
236
|
+
```ruby
|
237
|
+
handle_api_errors(error_id: :uuid)
|
238
|
+
```
|
30
239
|
|
31
|
-
|
240
|
+
Or pass a Proc if you need to do something custom.
|
241
|
+
```ruby
|
242
|
+
handle_api_errors(error_id: Proc.new { |error| SecureRandom.uuid })
|
243
|
+
```
|
32
244
|
|
33
|
-
|
245
|
+
These will result in:
|
246
|
+
```json
|
247
|
+
{
|
248
|
+
"error": {
|
249
|
+
"title": "Internal Server Error",
|
250
|
+
"detail": "Something is very very wrong!",
|
251
|
+
"id": "4ab520f2-ae33-4539-9371-ea21aada5582"
|
252
|
+
}
|
253
|
+
}
|
254
|
+
```
|
34
255
|
|
35
|
-
|
256
|
+
### Error Reporting
|
257
|
+
If you use an external error tracking software like Sentry or Honeybadger, you'll
|
258
|
+
want to report all errors to that service.
|
259
|
+
|
260
|
+
#### Out of the Box Error Reporting
|
261
|
+
There are a few supported error reporter options that you can select.
|
262
|
+
|
263
|
+
##### Raven/Sentry
|
264
|
+
```ruby
|
265
|
+
handle_api_errors(error_reporter: :raven)
|
266
|
+
# Or
|
267
|
+
handle_api_errors(error_reporter: :sentry)
|
268
|
+
```
|
269
|
+
|
270
|
+
##### Honeybadger
|
271
|
+
```ruby
|
272
|
+
handle_api_errors(error_reporter: :honeybadger)
|
273
|
+
```
|
274
|
+
|
275
|
+
__NOTE:__ If you use the `:error_id` option, the error error reporter will tag
|
276
|
+
the exception with the error ID when reporting the error.
|
277
|
+
|
278
|
+
#### Custom Reporting
|
279
|
+
If none of the out of the box options work for you, you can pass in a proc which
|
280
|
+
will receive the error and the error_id as arguments.
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
handle_api_errors(
|
284
|
+
error_reporter: Proc.new do |error, error_id|
|
285
|
+
# Do something with the `error` here.
|
286
|
+
end
|
287
|
+
)
|
288
|
+
```
|
289
|
+
|
290
|
+
### Setting Content Type
|
291
|
+
The api_error_handler will set the content type of your error based on the
|
292
|
+
`format` option you pick. However, you can override this by setting the
|
293
|
+
`content_type` option if you wish.
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
handle_api_errors(
|
297
|
+
format: :json,
|
298
|
+
content_type: 'application/vnd.api+json'
|
299
|
+
)
|
300
|
+
```
|
301
|
+
|
302
|
+
```json
|
303
|
+
HTTP/1.1 500 Internal Server Error
|
304
|
+
Content-Type: application/vnd.api+json
|
305
|
+
|
306
|
+
{
|
307
|
+
"error": {
|
308
|
+
"title":"Internal Server Error",
|
309
|
+
"detail":"Something is very very wrong!"
|
310
|
+
}
|
311
|
+
}
|
312
|
+
```
|
36
313
|
|
37
314
|
## License
|
38
315
|
|
data/Rakefile
CHANGED
data/api_error_handler.gemspec
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
lib = File.expand_path("../lib", __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
@@ -7,27 +8,40 @@ Gem::Specification.new do |spec|
|
|
7
8
|
spec.name = "api_error_handler"
|
8
9
|
spec.version = ApiErrorHandler::VERSION
|
9
10
|
spec.authors = ["James Stonehill"]
|
10
|
-
spec.email = ["
|
11
|
+
spec.email = ["james.stonehill@gmail.com"]
|
12
|
+
spec.required_ruby_version = ">= 2.5"
|
13
|
+
|
14
|
+
spec.summary = <<~SUMMARY
|
15
|
+
A gem that helps you easily handle exceptions in your Rails API and return
|
16
|
+
informative responses to the client.
|
17
|
+
SUMMARY
|
18
|
+
|
19
|
+
spec.description = <<~DESCRIPTION
|
20
|
+
A gem that helps you easily handle exceptions in your Ruby on Rails API and
|
21
|
+
return informative responses to the client by serializing exceptions into JSON
|
22
|
+
and other popular API formats and returning a response with a status code that
|
23
|
+
makes sense based on the exception.
|
24
|
+
DESCRIPTION
|
11
25
|
|
12
|
-
spec.summary = %q{A gem that helps you easily handle exptions in your Rails API and return informative responses to the client.}
|
13
|
-
spec.description = %q{A gem that helps you easily handle exptions in your Ruby on Rails API and return informative responses to the client by serializing exceptions into JSON and other popular API formats and returning a response with a status code that makes sense based on the exception.}
|
14
26
|
spec.homepage = "https://github.com/jamesstonehill/api_error_handler"
|
15
27
|
spec.license = "MIT"
|
16
28
|
|
17
29
|
# Specify which files should be added to the gem when it is released.
|
18
30
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
-
spec.files = Dir.chdir(File.expand_path(
|
20
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|
|
31
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|rails_.+)/}) }
|
21
33
|
end
|
22
34
|
spec.bindir = "exe"
|
23
35
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
36
|
spec.require_paths = ["lib"]
|
25
37
|
|
26
|
-
spec.add_dependency "activesupport", ">=
|
27
|
-
spec.add_dependency "actionpack"
|
38
|
+
spec.add_dependency "activesupport", ">= 5.0"
|
39
|
+
spec.add_dependency "actionpack", ">= 5.0"
|
40
|
+
spec.add_dependency "rack", ">= 1.0"
|
28
41
|
|
29
42
|
spec.add_development_dependency "bundler", "~> 2.0"
|
30
|
-
spec.add_development_dependency "rake", "~>
|
31
|
-
spec.add_development_dependency "rspec-rails", "~> 3.
|
32
|
-
spec.add_development_dependency "
|
43
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
44
|
+
spec.add_development_dependency "rspec-rails", "~> 3.9"
|
45
|
+
spec.add_development_dependency "rubocop", "~> 0.80.0"
|
46
|
+
spec.add_development_dependency "pry-byebug"
|
33
47
|
end
|
data/bin/console
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/lazy_load_hooks"
|
4
|
+
require "action_controller"
|
3
5
|
|
4
6
|
ActiveSupport.on_load :action_controller do
|
5
|
-
::ActionController::Base.
|
6
|
-
::ActionController::API.
|
7
|
+
::ActionController::Base.extend ApiErrorHandler
|
8
|
+
::ActionController::API.extend ApiErrorHandler
|
7
9
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
require_relative "./errors"
|
5
|
+
|
6
|
+
module ApiErrorHandler
|
7
|
+
class ErrorIdGenerator
|
8
|
+
def self.run(error_id_option)
|
9
|
+
if error_id_option.instance_of?(Proc)
|
10
|
+
error_id_option.call
|
11
|
+
elsif error_id_option == :uuid
|
12
|
+
SecureRandom.uuid
|
13
|
+
elsif error_id_option.nil?
|
14
|
+
nil
|
15
|
+
else
|
16
|
+
raise(
|
17
|
+
InvalidOptionError,
|
18
|
+
"Unable to handle `#{error_id_option}` as argument for the `:error_id` option."
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require_relative "./errors"
|
5
|
+
|
6
|
+
module ApiErrorHandler
|
7
|
+
class ErrorReporter
|
8
|
+
def initialize(strategy)
|
9
|
+
@strategy = strategy
|
10
|
+
end
|
11
|
+
|
12
|
+
def report(error, error_id: nil)
|
13
|
+
if @strategy.nil?
|
14
|
+
true
|
15
|
+
elsif @strategy.instance_of?(Proc)
|
16
|
+
@strategy.call(error, error_id)
|
17
|
+
elsif @strategy == :honeybadger
|
18
|
+
raise_dependency_error(missing_constant: "Honeybadger") unless defined?(Honeybadger)
|
19
|
+
|
20
|
+
context = error_id ? { error_id: error_id } : {}
|
21
|
+
Honeybadger.notify(error, context: context)
|
22
|
+
elsif @strategy == :raven
|
23
|
+
raise_dependency_error(missing_constant: "Raven") unless defined?(Raven)
|
24
|
+
|
25
|
+
extra = error_id ? { error_id: error_id } : {}
|
26
|
+
Raven.capture_exception(error, extra: extra)
|
27
|
+
elsif @strategy == :sentry
|
28
|
+
raise_dependency_error(missing_constant: "Sentry") unless defined?(Sentry)
|
29
|
+
|
30
|
+
extra = error_id ? { error_id: error_id } : {}
|
31
|
+
Sentry.capture_exception(error, extra: extra)
|
32
|
+
else
|
33
|
+
raise(
|
34
|
+
InvalidOptionError,
|
35
|
+
"`#{@strategy.inspect}` is an invalid argument for the `:error_id` option."
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def raise_dependency_error(missing_constant:)
|
43
|
+
raise MissingDependencyError, <<~MESSAGE
|
44
|
+
You selected the #{@strategy.inspect} error reporter option but the
|
45
|
+
#{missing_constant} constant is not defined. If you wish to use this
|
46
|
+
error reporting option you must have the #{@strategy} client gem
|
47
|
+
installed.
|
48
|
+
MESSAGE
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack/utils"
|
4
|
+
|
5
|
+
module ApiErrorHandler
|
6
|
+
module Serializers
|
7
|
+
class BaseSerializer
|
8
|
+
DEFAULT_STATUS_CODE = "500"
|
9
|
+
|
10
|
+
def initialize(error, status)
|
11
|
+
@error = error
|
12
|
+
@status = status
|
13
|
+
end
|
14
|
+
|
15
|
+
def status_code
|
16
|
+
Rack::Utils::SYMBOL_TO_STATUS_CODE.fetch(@status, DEFAULT_STATUS_CODE).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def title
|
20
|
+
Rack::Utils::HTTP_STATUS_CODES.fetch(status_code.to_i)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,6 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base_serializer"
|
4
|
+
|
1
5
|
module ApiErrorHandler
|
2
6
|
module Serializers
|
3
|
-
class Json
|
7
|
+
class Json < BaseSerializer
|
8
|
+
# There is no official spec that governs this error response format so
|
9
|
+
# this serializer is just trying to impliment a simple response with
|
10
|
+
# sensible defaults.
|
11
|
+
#
|
12
|
+
# I borrowed heavily from Facebook's error response format since it seems
|
13
|
+
# to be a reasonable approach for a simple light-weight error response.
|
14
|
+
|
15
|
+
def serialize(options = {})
|
16
|
+
body = {
|
17
|
+
error: {
|
18
|
+
title: title,
|
19
|
+
detail: @error.message,
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
body[:error][:id] = options[:error_id] if options[:error_id]
|
24
|
+
body[:error][:backtrace] = @error.backtrace if options[:backtrace]
|
25
|
+
|
26
|
+
body.to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_format
|
30
|
+
:json
|
31
|
+
end
|
4
32
|
end
|
5
33
|
end
|
6
34
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./base_serializer"
|
4
|
+
|
5
|
+
module ApiErrorHandler
|
6
|
+
module Serializers
|
7
|
+
class JsonApi < BaseSerializer
|
8
|
+
def serialize(options = {})
|
9
|
+
body = {
|
10
|
+
errors: [
|
11
|
+
{
|
12
|
+
status: status_code,
|
13
|
+
title: title,
|
14
|
+
detail: @error.message,
|
15
|
+
}
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
body[:errors].first[:id] = options[:error_id] if options[:error_id]
|
20
|
+
body[:errors].first[:meta] = { backtrace: @error.backtrace } if options[:backtrace]
|
21
|
+
|
22
|
+
body.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_format
|
26
|
+
:json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/conversions"
|
4
|
+
require_relative "./base_serializer"
|
5
|
+
|
6
|
+
module ApiErrorHandler
|
7
|
+
module Serializers
|
8
|
+
class Xml < BaseSerializer
|
9
|
+
def serialize(options = {})
|
10
|
+
body = {
|
11
|
+
Title: title,
|
12
|
+
Detail: @error.message,
|
13
|
+
}
|
14
|
+
|
15
|
+
body[:Id] = options[:error_id] if options[:error_id]
|
16
|
+
body[:Backtrace] = @error.backtrace if options[:backtrace]
|
17
|
+
|
18
|
+
body.to_xml(root: "Error")
|
19
|
+
end
|
20
|
+
|
21
|
+
def render_format
|
22
|
+
:xml
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/api_error_handler.rb
CHANGED
@@ -1,11 +1,55 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./api_error_handler/version"
|
4
|
+
require_relative "./api_error_handler/action_controller"
|
5
|
+
require_relative "./api_error_handler/error_id_generator"
|
6
|
+
require_relative "./api_error_handler/error_reporter"
|
7
|
+
Dir[File.join(__dir__, "api_error_handler", "serializers", "*.rb")].sort.each do |file|
|
8
|
+
require file
|
9
|
+
end
|
3
10
|
|
4
11
|
module ApiErrorHandler
|
5
|
-
|
12
|
+
SERIALIZERS_BY_FORMAT = {
|
13
|
+
json: Serializers::Json,
|
14
|
+
json_api: Serializers::JsonApi,
|
15
|
+
xml: Serializers::Xml,
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
SERIALIZER_OPTIONS = {
|
19
|
+
backtrace: false,
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
CONTENT_TYPE_BY_FORMAT = {
|
23
|
+
json_api: "application/vnd.api+json"
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
def handle_api_errors(options = {})
|
27
|
+
format = options.fetch(:format, :json)
|
28
|
+
error_reporter = ErrorReporter.new(options[:error_reporter])
|
29
|
+
serializer_options = SERIALIZER_OPTIONS.merge(
|
30
|
+
options.slice(*SERIALIZER_OPTIONS.keys)
|
31
|
+
)
|
32
|
+
|
33
|
+
serializer_class = options[:serializer] || SERIALIZERS_BY_FORMAT.fetch(format)
|
34
|
+
content_type = options[:content_type] || CONTENT_TYPE_BY_FORMAT[format]
|
35
|
+
rescue_from StandardError do |error|
|
36
|
+
status = ActionDispatch::ExceptionWrapper.rescue_responses[error.class.to_s]
|
37
|
+
|
38
|
+
error_id = ErrorIdGenerator.run(options[:error_id])
|
39
|
+
error_reporter.report(error, error_id: error_id)
|
40
|
+
|
41
|
+
serializer = serializer_class.new(error, status)
|
42
|
+
response_body = serializer.serialize(
|
43
|
+
serializer_options.merge(error_id: error_id)
|
44
|
+
)
|
6
45
|
|
7
|
-
|
8
|
-
|
46
|
+
render(
|
47
|
+
serializer.render_format => response_body,
|
48
|
+
content_type: content_type,
|
49
|
+
status: status
|
50
|
+
)
|
51
|
+
rescue
|
52
|
+
raise error
|
9
53
|
end
|
10
54
|
end
|
11
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_error_handler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Stonehill
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '5.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '5.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: actionpack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '5.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,30 +72,44 @@ dependencies:
|
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '13.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec-rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3.
|
89
|
+
version: '3.9'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3.
|
96
|
+
version: '3.9'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.80.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.80.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-byebug
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
86
114
|
requirements:
|
87
115
|
- - ">="
|
@@ -94,21 +122,24 @@ dependencies:
|
|
94
122
|
- - ">="
|
95
123
|
- !ruby/object:Gem::Version
|
96
124
|
version: '0'
|
97
|
-
description:
|
98
|
-
|
99
|
-
|
100
|
-
|
125
|
+
description: |
|
126
|
+
A gem that helps you easily handle exceptions in your Ruby on Rails API and
|
127
|
+
return informative responses to the client by serializing exceptions into JSON
|
128
|
+
and other popular API formats and returning a response with a status code that
|
129
|
+
makes sense based on the exception.
|
101
130
|
email:
|
102
|
-
-
|
131
|
+
- james.stonehill@gmail.com
|
103
132
|
executables: []
|
104
133
|
extensions: []
|
105
134
|
extra_rdoc_files: []
|
106
135
|
files:
|
107
136
|
- ".gitignore"
|
108
137
|
- ".rspec"
|
138
|
+
- ".rubocop.yml"
|
139
|
+
- ".rubocop_todo.yml"
|
140
|
+
- ".ruby-version"
|
109
141
|
- ".travis.yml"
|
110
142
|
- Gemfile
|
111
|
-
- Gemfile.lock
|
112
143
|
- LICENSE.txt
|
113
144
|
- README.md
|
114
145
|
- Rakefile
|
@@ -117,10 +148,14 @@ files:
|
|
117
148
|
- bin/setup
|
118
149
|
- lib/api_error_handler.rb
|
119
150
|
- lib/api_error_handler/action_controller.rb
|
120
|
-
- lib/api_error_handler/
|
151
|
+
- lib/api_error_handler/error_id_generator.rb
|
152
|
+
- lib/api_error_handler/error_reporter.rb
|
153
|
+
- lib/api_error_handler/errors.rb
|
154
|
+
- lib/api_error_handler/serializers/base_serializer.rb
|
121
155
|
- lib/api_error_handler/serializers/json.rb
|
156
|
+
- lib/api_error_handler/serializers/json_api.rb
|
157
|
+
- lib/api_error_handler/serializers/xml.rb
|
122
158
|
- lib/api_error_handler/version.rb
|
123
|
-
- lib/serializers/json.rb
|
124
159
|
homepage: https://github.com/jamesstonehill/api_error_handler
|
125
160
|
licenses:
|
126
161
|
- MIT
|
@@ -133,17 +168,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
168
|
requirements:
|
134
169
|
- - ">="
|
135
170
|
- !ruby/object:Gem::Version
|
136
|
-
version: '
|
171
|
+
version: '2.5'
|
137
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
173
|
requirements:
|
139
|
-
- - "
|
174
|
+
- - ">="
|
140
175
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
176
|
+
version: '0'
|
142
177
|
requirements: []
|
143
|
-
|
144
|
-
rubygems_version: 2.6.14.4
|
178
|
+
rubygems_version: 3.0.3.1
|
145
179
|
signing_key:
|
146
180
|
specification_version: 4
|
147
|
-
summary: A gem that helps you easily handle
|
181
|
+
summary: A gem that helps you easily handle exceptions in your Rails API and return
|
148
182
|
informative responses to the client.
|
149
183
|
test_files: []
|
data/Gemfile.lock
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
api_error_handler (0.1.0)
|
5
|
-
actionpack
|
6
|
-
activesupport (>= 4.1.0)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
actionpack (5.2.3)
|
12
|
-
actionview (= 5.2.3)
|
13
|
-
activesupport (= 5.2.3)
|
14
|
-
rack (~> 2.0)
|
15
|
-
rack-test (>= 0.6.3)
|
16
|
-
rails-dom-testing (~> 2.0)
|
17
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
-
actionview (5.2.3)
|
19
|
-
activesupport (= 5.2.3)
|
20
|
-
builder (~> 3.1)
|
21
|
-
erubi (~> 1.4)
|
22
|
-
rails-dom-testing (~> 2.0)
|
23
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
-
activesupport (5.2.3)
|
25
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
26
|
-
i18n (>= 0.7, < 2)
|
27
|
-
minitest (~> 5.1)
|
28
|
-
tzinfo (~> 1.1)
|
29
|
-
builder (3.2.3)
|
30
|
-
coderay (1.1.2)
|
31
|
-
concurrent-ruby (1.1.5)
|
32
|
-
crass (1.0.4)
|
33
|
-
diff-lcs (1.3)
|
34
|
-
erubi (1.8.0)
|
35
|
-
i18n (1.6.0)
|
36
|
-
concurrent-ruby (~> 1.0)
|
37
|
-
loofah (2.2.3)
|
38
|
-
crass (~> 1.0.2)
|
39
|
-
nokogiri (>= 1.5.9)
|
40
|
-
method_source (0.9.2)
|
41
|
-
mini_portile2 (2.4.0)
|
42
|
-
minitest (5.11.3)
|
43
|
-
nokogiri (1.10.3)
|
44
|
-
mini_portile2 (~> 2.4.0)
|
45
|
-
pry (0.12.2)
|
46
|
-
coderay (~> 1.1.0)
|
47
|
-
method_source (~> 0.9.0)
|
48
|
-
rack (2.0.7)
|
49
|
-
rack-test (1.1.0)
|
50
|
-
rack (>= 1.0, < 3)
|
51
|
-
rails-dom-testing (2.0.3)
|
52
|
-
activesupport (>= 4.2.0)
|
53
|
-
nokogiri (>= 1.6)
|
54
|
-
rails-html-sanitizer (1.0.4)
|
55
|
-
loofah (~> 2.2, >= 2.2.2)
|
56
|
-
railties (5.2.3)
|
57
|
-
actionpack (= 5.2.3)
|
58
|
-
activesupport (= 5.2.3)
|
59
|
-
method_source
|
60
|
-
rake (>= 0.8.7)
|
61
|
-
thor (>= 0.19.0, < 2.0)
|
62
|
-
rake (10.5.0)
|
63
|
-
rspec-core (3.8.2)
|
64
|
-
rspec-support (~> 3.8.0)
|
65
|
-
rspec-expectations (3.8.4)
|
66
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
-
rspec-support (~> 3.8.0)
|
68
|
-
rspec-mocks (3.8.1)
|
69
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
70
|
-
rspec-support (~> 3.8.0)
|
71
|
-
rspec-rails (3.8.2)
|
72
|
-
actionpack (>= 3.0)
|
73
|
-
activesupport (>= 3.0)
|
74
|
-
railties (>= 3.0)
|
75
|
-
rspec-core (~> 3.8.0)
|
76
|
-
rspec-expectations (~> 3.8.0)
|
77
|
-
rspec-mocks (~> 3.8.0)
|
78
|
-
rspec-support (~> 3.8.0)
|
79
|
-
rspec-support (3.8.2)
|
80
|
-
thor (0.20.3)
|
81
|
-
thread_safe (0.3.6)
|
82
|
-
tzinfo (1.2.5)
|
83
|
-
thread_safe (~> 0.1)
|
84
|
-
|
85
|
-
PLATFORMS
|
86
|
-
ruby
|
87
|
-
|
88
|
-
DEPENDENCIES
|
89
|
-
api_error_handler!
|
90
|
-
bundler (~> 2.0)
|
91
|
-
pry
|
92
|
-
rake (~> 10.0)
|
93
|
-
rspec-rails (~> 3.0)
|
94
|
-
|
95
|
-
BUNDLED WITH
|
96
|
-
2.0.2
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require_relative 'serializers/json'
|
2
|
-
|
3
|
-
module ApiErrorHandler
|
4
|
-
class ErrorSerializer
|
5
|
-
SERIALIZERS_BY_FORMAT = {
|
6
|
-
json: Serializers::Json
|
7
|
-
}
|
8
|
-
|
9
|
-
def initialize(error, format, status)
|
10
|
-
@error = error
|
11
|
-
@format = format
|
12
|
-
@status = status
|
13
|
-
end
|
14
|
-
|
15
|
-
def serialize
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def serializer
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|