egregious 0.2.10 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +14 -0
- data/Appraisals +8 -0
- data/Gemfile +0 -7
- data/README.md +265 -0
- data/Rakefile +11 -0
- data/egregious.gemspec +3 -3
- data/gemfiles/rails_3.gemfile +8 -0
- data/gemfiles/rails_4.gemfile +7 -0
- data/lib/egregious.rb +22 -28
- data/lib/egregious/version.rb +1 -1
- data/spec/apps/rails3_2.rb +52 -0
- data/spec/apps/rails4.rb +69 -0
- data/spec/controllers/controller_spec.rb +20 -0
- data/spec/egregious_spec.rb +1 -1
- data/spec/notify_airbrake_spec.rb +34 -0
- data/spec/spec_helper.rb +24 -5
- metadata +32 -6
- data/README +0 -146
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f054b5425e665f2ebda249fb5df5e8f89b39f96
|
4
|
+
data.tar.gz: a0b34cdbdd5fbd5938c9436c8d62b0f0c454033b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c782e63e62b4cf4013beee5d097ed70f4c304e3893edfbdaf58a519240d6621c363fe88370e38e52f15b74f290b2fcc92e19c0245c43d9f54f95f8c3f74937a1
|
7
|
+
data.tar.gz: 653ae2c6121911c6c46f6931450b8ff0141d532676b4003372fe557e332ab6066ad38ca8a603507b4410a1e560103d48f080be666113e0f55e212df57e5ea4ee
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
gemfile:
|
3
|
+
- gemfiles/rails_3.gemfile
|
4
|
+
- gemfiles/rails_4.gemfile
|
5
|
+
rvm:
|
6
|
+
- "1.9.3"
|
7
|
+
- "2.2.3"
|
8
|
+
|
9
|
+
#matrix:
|
10
|
+
# allow_failures:
|
11
|
+
# - env: "RAILS_VERSION=master"
|
12
|
+
# - rvm: ruby-head
|
13
|
+
# uncomment this line if your project needs to run something other than `rake`:
|
14
|
+
# script: bundle exec rspec spec
|
data/Appraisals
ADDED
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/voomify/egregious.svg?branch=master)](https://travis-ci.org/voomify/egregious)
|
2
|
+
##### Update Log:
|
3
|
+
|
4
|
+
* Version 0.2.12 Added support for Airbrake 5
|
5
|
+
|
6
|
+
* Version 0.2.11 Fixed the development behavior that does not show the debugging screens when exceptions
|
7
|
+
are thrown. Now when in development you will get the rails default exception handling screens for html requests.
|
8
|
+
|
9
|
+
* Version 0.2.10 released to https://rubygems.org/gems/egregious on 10.28.2015
|
10
|
+
Fixed bug where an exception defines http_status but returns nil.
|
11
|
+
This was resulting in a status of 200 being returned, when it should be a 500.
|
12
|
+
|
13
|
+
If you would like to contribute take a look at the issues feature list, fork and issue a pull request!
|
14
|
+
|
15
|
+
##### What is Egregious?
|
16
|
+
Egregious is a rails based exception handling gem for well defined http exception handling for
|
17
|
+
json, xml and html.
|
18
|
+
|
19
|
+
If you have a json or xml api into your rails application, you probably have added your own exception handling to map
|
20
|
+
exceptions to a http status and formatting your json and xml output. We decided to create egregious. One of the goals
|
21
|
+
is to start providing a more consistent api error experience for all rails applications. As of the creation of
|
22
|
+
egregious the behavior of rails was to return html when an exception is thrown with the status code of 500. With
|
23
|
+
egregious proper json and html of the error will be returned with a good default mapping of exceptions to http status
|
24
|
+
codes. This allows api developers to respond to the status code properly, instead of scratching their head with 500's
|
25
|
+
coming back all the time. If the problem was the api caller then the result codes are in the 300 range. If the problem
|
26
|
+
was on the server then the status codes are in the 500 range. The returned exception message and exception type
|
27
|
+
provide the caller context information.
|
28
|
+
|
29
|
+
What egregious can do:
|
30
|
+
|
31
|
+
* Defines default exception handling for most common ruby, rails, warden, cancan and mongoid exceptions.
|
32
|
+
(warden, cancan and mongoid are optional)
|
33
|
+
* Catches defined exceptions using a rescue_with returning the status code defined for each exception
|
34
|
+
and well structured json, xml
|
35
|
+
* For html production requests attempts to load the html error pages for the mapped status code,
|
36
|
+
falling back to the 500.html page.
|
37
|
+
* Defines exceptions for all http status codes allowing you to throw these exceptions anywhere in your code.
|
38
|
+
* Allows you to change the exception mapping to fit your needs, adding exceptions and changing status mapping.
|
39
|
+
* If Airbrake is defined it will send the errors to Airbrake.
|
40
|
+
* The error will be logged with stack trace
|
41
|
+
|
42
|
+
|
43
|
+
##### REQUIRES:
|
44
|
+
rails > 3.0, < 5.0
|
45
|
+
rack >= 1.3.6
|
46
|
+
|
47
|
+
##### USAGE:
|
48
|
+
1) Add to your Gemfile:
|
49
|
+
```ruby
|
50
|
+
gem 'egregious'
|
51
|
+
```
|
52
|
+
|
53
|
+
2) In your ApplicationController add:
|
54
|
+
```ruby
|
55
|
+
include Egregious
|
56
|
+
```
|
57
|
+
|
58
|
+
##### KNOWN ISSUES:
|
59
|
+
* If you use Mongoid, CanCan or Devise you must have Egregious after CanCan/Devise in your Gemfile, if not it will not handle those errors correctly.
|
60
|
+
|
61
|
+
##### Implementation Notes
|
62
|
+
If you have a json or xml api into your rails application, you probably
|
63
|
+
have added your own exception handling to map exceptions to a http status and formatting your json and xml output.
|
64
|
+
|
65
|
+
|
66
|
+
You probably have code sprinkled about like this:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
rescue_from CanCan::AccessDenied do |exception|
|
70
|
+
flash[:alert] = exception.message
|
71
|
+
respond_to do |format|
|
72
|
+
format.html { redirect_to dashboard_path }
|
73
|
+
format.xml {
|
74
|
+
render :xml => exception.to_xml, :status => :forbidden }
|
75
|
+
format.json { render :json=>
|
76
|
+
exception.to_json, :status => :forbidden }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
This example is straight from the CanCan docs. You'll notice a couple of things here. This handles the
|
82
|
+
CanCan::AccessDenied exception only. It then will redirect to the startup page, or render xml and json returning
|
83
|
+
the http status code of :forbidden (403). You can see one of the first features of the Egregious gem. We extend
|
84
|
+
Exception to add the to_xml and to_json methods. These return a well structured error that can be consumed by the
|
85
|
+
API client.
|
86
|
+
```ruby
|
87
|
+
Exception.new("Hi Mom").to_xml
|
88
|
+
```
|
89
|
+
returns:
|
90
|
+
```xml
|
91
|
+
<errors>
|
92
|
+
<error>Hi Mom</error>
|
93
|
+
<type>Exception</type>
|
94
|
+
</errors>
|
95
|
+
```
|
96
|
+
```ruby
|
97
|
+
Exception.new("Hi Dad").to_json
|
98
|
+
```
|
99
|
+
returns:
|
100
|
+
```json
|
101
|
+
{"error":"Hi Dad", "type":"Exception"}
|
102
|
+
```
|
103
|
+
|
104
|
+
So that's pretty handy in itself. Now all exceptions have a json and xml api that describe them. It happens to be the same
|
105
|
+
xml and json that is returned from the errors active record object, with the addition of the type element. That
|
106
|
+
allows you to mix and match validations and exceptions. Wow, big deal. We'll it is. If you are writing a client
|
107
|
+
then you need to have a very well defined error handling. I'd like to see all of rails do this by default. So that
|
108
|
+
anyone interacting with a rails resource has a consistent error handling experience. (Expect more on being a good
|
109
|
+
REST API in future posts.) As a client we can now handle errors in a consistent way.
|
110
|
+
|
111
|
+
Besides the error message we would like a well defined mapping of classes of exceptions to http status codes. The idea is
|
112
|
+
that if I get back a specific http status code then I can program against that 'class' of problems. For example if
|
113
|
+
I know that what I did was because of invalid input from my user, I can display that message back to the user.
|
114
|
+
They can correct it and continue down the path. But if the Http status code says that it was a problem with the
|
115
|
+
server, then I know that I need to log it and notify someone to see how to resolve it.
|
116
|
+
|
117
|
+
We handle all exceptions of a given class with a mapping to an http status code. With all the most common Ruby,
|
118
|
+
Rails, Devise, Warden and CanCan exceptions having reasonable defaults. (Devise, Warden and CanCan are all
|
119
|
+
optional and ignored if their gems are not installed.)
|
120
|
+
|
121
|
+
As of 0.2.9 you can also define a
|
122
|
+
method named 'http_status' on the exception and it will be used as the status code. This is a nice pattern that
|
123
|
+
allows you to raise an exception and specify the status code. The Egregious::Error allows you to do this as a
|
124
|
+
second parameter to initialize:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
raise Egregious::Error.new("My very bad error", :payment_required)
|
128
|
+
```
|
129
|
+
|
130
|
+
|
131
|
+
If the problem
|
132
|
+
was the api caller then the result codes are in the 300 range. If the problem was on the server then the status
|
133
|
+
codes are in the 500 range.
|
134
|
+
|
135
|
+
I'm guessing if you bother to read this far, you are probably
|
136
|
+
interested in using Egregious. Its simple to use and configure. To install:
|
137
|
+
|
138
|
+
In you Gemfile
|
139
|
+
add the following:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
gem 'egregious'
|
143
|
+
```
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
In
|
148
|
+
your ApplicationController class add the following at or near the top:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class ApplicationController < ActionController::Base
|
152
|
+
include Egregious
|
153
|
+
# your code ...
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
That's it. You will now get
|
160
|
+
reasonable api error handling.
|
161
|
+
|
162
|
+
If you want to add your own exceptions to http status codes
|
163
|
+
end
|
164
|
+
mappings, or change the defaults add an initializer and put the following into it:
|
165
|
+
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
Egregious.exception_codes.merge!({NameError => :bad_request})
|
169
|
+
```
|
170
|
+
|
171
|
+
|
172
|
+
Here
|
173
|
+
you can re-map anything and you can add new mappings.
|
174
|
+
|
175
|
+
Note: If you think the default
|
176
|
+
exception mappings should be different, please contact me @rx via the
|
177
|
+
https://github.com/voomify/egregious project.
|
178
|
+
|
179
|
+
We also
|
180
|
+
created exceptions for each of the http status codes, so that you can throw those exceptions in your code. Its an
|
181
|
+
easy way to throw the right status code and setup a good message for it. If you want to provide more context, you
|
182
|
+
can derive you own exceptions and add mappings for them.
|
183
|
+
|
184
|
+
Here is an example of throwing a
|
185
|
+
bad request exception:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
raise Egregious::BadRequest.new("You can not created an order without a customer.") unless customer_id
|
189
|
+
```
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
Egregious adds
|
194
|
+
mapping of many exceptions, if you have your own rescue_from handlers those will get invoked. You will not lose
|
195
|
+
any existing behavior, but you also might not see the changes you expect until you remove or modify those
|
196
|
+
rescue_from calls. At a minimum I suggest using the .to_xml and .to_json calls io your existing rescue_from
|
197
|
+
methods/blocks.
|
198
|
+
|
199
|
+
And finally if you don't like the default behavior. You can override any
|
200
|
+
portion of it and change it to meet your needs.
|
201
|
+
|
202
|
+
If you want to change the behavior then you
|
203
|
+
can override the following methods in your ApplicationController.
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
# override this if you want your flash to behave differently
|
207
|
+
def egregious_flash(exception)
|
208
|
+
flash.now[:alert] = exception.message
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
# override this if you want your logging to behave differently
|
215
|
+
def
|
216
|
+
egregious_log(exception)
|
217
|
+
logger.fatal(
|
218
|
+
"\n\n" + exception.class.to_s + ' (' +
|
219
|
+
exception.message.to_s + '):\n ' +
|
220
|
+
clean_backtrace(exception).join("\n ") +
|
221
|
+
"\n\n")
|
222
|
+
HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
|
223
|
+
end
|
224
|
+
```
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
# override this if you want to change your respond_to behavior
|
228
|
+
def egregious_respond_to(exception)
|
229
|
+
respond_to do |format|
|
230
|
+
status = status_code_for_exception(exception)
|
231
|
+
format.xml { render :xml=> exception.to_xml, :status => status }
|
232
|
+
format.json { render :json=> exception.to_json, :status => status }
|
233
|
+
# render the html page for the status we are returning it exists...if not then render the 500.html page.
|
234
|
+
format.html { render :file => File.exists?(build_html_file_path(status)) ?
|
235
|
+
build_html_file_path(status) : build_html_file_path('500')}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
```
|
239
|
+
```ruby
|
240
|
+
# override this if you want to change what html static file gets returned.
|
241
|
+
def build_html_file_path(status)
|
242
|
+
File.expand_path(Rails.root, 'public', status + '.html')
|
243
|
+
end
|
244
|
+
```
|
245
|
+
|
246
|
+
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
# override this if you want to control what gets sent to airbrake
|
250
|
+
# optionally you can configure the airbrake ignore list
|
251
|
+
def notify_airbrake(exception)
|
252
|
+
# tested with airbrake 3.1.15, 4.2.1 and 5.0.5
|
253
|
+
if defined?(Airbrake)
|
254
|
+
if(Airbrake.respond_to?(:notify_or_ignore))
|
255
|
+
env['airbrake.error_id'] = Airbrake.notify_or_ignore(exception) # V4
|
256
|
+
else
|
257
|
+
env['airbrake.error_id'] = Airbrake.notify(exception) # V5
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
We are using this gem in all our Rails projects.
|
264
|
+
|
265
|
+
Go forth and be egregious!
|
data/Rakefile
CHANGED
@@ -1 +1,12 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
1
3
|
require "bundler/gem_tasks"
|
4
|
+
|
5
|
+
require 'rake'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.pattern = Dir.glob('spec/**/*_spec.rb')
|
10
|
+
t.rspec_opts = '--format documentation'
|
11
|
+
end
|
12
|
+
task :default => :spec
|
data/egregious.gemspec
CHANGED
@@ -20,17 +20,17 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
|
22
22
|
s.add_runtime_dependency "rails", '> 3.0', '< 5'
|
23
|
-
s.add_runtime_dependency "rack", '>= 1.
|
23
|
+
s.add_runtime_dependency "rack", '>= 1.2.5'
|
24
24
|
s.add_runtime_dependency "htmlentities"
|
25
25
|
|
26
26
|
# specify any dependencies here; for example:
|
27
27
|
s.add_development_dependency "rspec"
|
28
|
+
s.add_development_dependency "rspec-rails"
|
28
29
|
s.add_development_dependency "json"
|
29
30
|
s.add_development_dependency "hpricot"
|
30
31
|
s.add_development_dependency "warden"
|
31
32
|
s.add_development_dependency "cancan"
|
32
33
|
s.add_development_dependency "mongoid"
|
33
|
-
s.add_development_dependency "
|
34
|
-
|
34
|
+
s.add_development_dependency "appraisal"
|
35
35
|
|
36
36
|
end
|
data/lib/egregious.rb
CHANGED
@@ -96,7 +96,7 @@ module Egregious
|
|
96
96
|
Mongoid::Errors::Validations=>status_code(:unprocessable_entity)
|
97
97
|
})
|
98
98
|
|
99
|
-
if Mongoid::VERSION > '3'
|
99
|
+
if defined?(Mongoid::VERSION) && Mongoid::VERSION > '3'
|
100
100
|
exception_codes.merge!({
|
101
101
|
Mongoid::Errors::ReadonlyAttribute=>status_code(:forbidden),
|
102
102
|
Mongoid::Errors::UnknownAttribute=>status_code(:bad_request)
|
@@ -137,7 +137,9 @@ module Egregious
|
|
137
137
|
def clean_backtrace(exception)
|
138
138
|
if backtrace = exception.backtrace
|
139
139
|
if Egregious.root
|
140
|
-
backtrace.map { |line|
|
140
|
+
backtrace.map { |line|
|
141
|
+
line.sub Egregious.root.to_s, ''
|
142
|
+
}
|
141
143
|
else
|
142
144
|
backtrace
|
143
145
|
end
|
@@ -173,7 +175,7 @@ module Egregious
|
|
173
175
|
# if the exception is not in our map then see if the class responds to :http_status
|
174
176
|
# if not it will return 500
|
175
177
|
def status_code_for_exception(exception)
|
176
|
-
|
178
|
+
Egregious.status_code_for_exception(exception)
|
177
179
|
end
|
178
180
|
|
179
181
|
def self.status_code_for_exception(exception)
|
@@ -204,10 +206,14 @@ module Egregious
|
|
204
206
|
|
205
207
|
# override this if you want to control what gets sent to airbrake
|
206
208
|
def notify_airbrake(exception)
|
207
|
-
#
|
208
|
-
|
209
|
-
|
210
|
-
|
209
|
+
# tested with airbrake 3.1.15, 4.2.1 and 5.0.5
|
210
|
+
if defined?(Airbrake)
|
211
|
+
if(Airbrake.respond_to?(:notify_or_ignore))
|
212
|
+
env['airbrake.error_id'] = Airbrake.notify_or_ignore(exception) # V4
|
213
|
+
else
|
214
|
+
env['airbrake.error_id'] = Airbrake.notify(exception) # V5
|
215
|
+
end
|
216
|
+
end
|
211
217
|
end
|
212
218
|
|
213
219
|
# override this if you want to change your respond_to behavior
|
@@ -217,9 +223,16 @@ module Egregious
|
|
217
223
|
format.xml { render :xml=> exception.to_xml, :status => status }
|
218
224
|
format.json { render :json=> exception.to_json, :status => status }
|
219
225
|
# render the html page for the status we are returning it exists...if not then render the 500.html page.
|
220
|
-
format.html {
|
226
|
+
format.html {
|
227
|
+
# render the rails exception page if we are local/debugging
|
228
|
+
if(Rails.application.config.consider_all_requests_local || request.local?)
|
229
|
+
raise exception
|
230
|
+
else
|
231
|
+
render :file => File.exists?(build_html_file_path(status)) ?
|
221
232
|
build_html_file_path(status) : build_html_file_path('500'),
|
222
|
-
:status => status
|
233
|
+
:status => status
|
234
|
+
end
|
235
|
+
}
|
223
236
|
end
|
224
237
|
end
|
225
238
|
|
@@ -230,25 +243,6 @@ module Egregious
|
|
230
243
|
def self.included(base)
|
231
244
|
base.class_eval do
|
232
245
|
rescue_from 'Exception' , :with => :egregious_exception_handler
|
233
|
-
|
234
|
-
unless respond_to?(:flash)
|
235
|
-
def egregious_flash(exception)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
unless respond_to?(:respond_to)
|
240
|
-
def egregious_respond_to(exception)
|
241
|
-
status = status_code_for_exception(exception)
|
242
|
-
case params[:format]
|
243
|
-
when 'xml' then render :xml=> exception.to_xml, :status => status
|
244
|
-
when 'json' then render :json=> exception.to_json, :status => status
|
245
|
-
# render the html page for the status we are returning it exists...if not then render the 500.html page.
|
246
|
-
else render :file => File.exists?(build_html_file_path(status)) ?
|
247
|
-
build_html_file_path(status) : build_html_file_path('500'),
|
248
|
-
:status => status
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
246
|
end
|
253
247
|
end
|
254
248
|
end
|
data/lib/egregious/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# http://www.rubytutorial.io/how-to-test-your-gem-against-multiple-rails/
|
2
|
+
require "action_controller/railtie"
|
3
|
+
require "action_mailer/railtie"
|
4
|
+
require "active_resource/railtie"
|
5
|
+
require "rails/test_unit/railtie"
|
6
|
+
require "sprockets/railtie"
|
7
|
+
require 'action_view/testing/resolvers'
|
8
|
+
require 'rails/test_help'
|
9
|
+
|
10
|
+
require 'egregious' # our gem
|
11
|
+
|
12
|
+
class Rails3_2 < Rails::Application
|
13
|
+
config.root = File.expand_path("../../..", __FILE__)
|
14
|
+
config.cache_classes = true
|
15
|
+
|
16
|
+
config.eager_load = false
|
17
|
+
config.serve_static_assets = true
|
18
|
+
config.static_cache_control = "public, max-age=3600"
|
19
|
+
|
20
|
+
config.consider_all_requests_local = true
|
21
|
+
config.action_controller.perform_caching = false
|
22
|
+
|
23
|
+
config.action_dispatch.show_exceptions = false
|
24
|
+
|
25
|
+
config.action_controller.allow_forgery_protection = false
|
26
|
+
|
27
|
+
config.active_support.deprecation = :stderr
|
28
|
+
|
29
|
+
config.middleware.delete "Rack::Lock"
|
30
|
+
config.middleware.delete "ActionDispatch::Flash"
|
31
|
+
config.middleware.delete "ActionDispatch::BestStandardsSupport"
|
32
|
+
config.secret_token = "49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk"
|
33
|
+
routes.append do
|
34
|
+
get "/" => "welcome#index"
|
35
|
+
get "/" => "fake#test"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class WelcomeController < ActionController::Base
|
40
|
+
include Rails.application.routes.url_helpers
|
41
|
+
layout 'application'
|
42
|
+
self.view_paths = [ActionView::FixtureResolver.new(
|
43
|
+
"layouts/application.html.erb" => '<%= yield %>',
|
44
|
+
"welcome/index.html.erb"=> 'Hello from index.html.erb',
|
45
|
+
)]
|
46
|
+
|
47
|
+
def index
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
Rails3_2.initialize!
|
data/spec/apps/rails4.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#http://www.rubytutorial.io/how-to-test-your-gem-against-multiple-rails/
|
2
|
+
require "action_controller/railtie"
|
3
|
+
require "action_mailer/railtie"
|
4
|
+
require "sprockets/railtie"
|
5
|
+
require "rails/test_unit/railtie"
|
6
|
+
require 'action_view/testing/resolvers'
|
7
|
+
|
8
|
+
require 'egregious' # our gem
|
9
|
+
|
10
|
+
# monkey patch - we don't want fixtures loaded, because we don't configure or test ActiveRecord
|
11
|
+
# https://github.com/rspec/rspec-rails/issues/1416
|
12
|
+
module ActiveRecord
|
13
|
+
module TestFixtures
|
14
|
+
def before_setup
|
15
|
+
super
|
16
|
+
end
|
17
|
+
def after_teardown
|
18
|
+
super
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Rails4
|
25
|
+
class Application < Rails::Application
|
26
|
+
config.root = File.expand_path("../../..", __FILE__)
|
27
|
+
config.cache_classes = true
|
28
|
+
|
29
|
+
config.eager_load = false
|
30
|
+
config.serve_static_assets = true
|
31
|
+
config.static_cache_control = "public, max-age=3600"
|
32
|
+
|
33
|
+
config.consider_all_requests_local = true
|
34
|
+
config.action_controller.perform_caching = false
|
35
|
+
|
36
|
+
config.action_dispatch.show_exceptions = false
|
37
|
+
|
38
|
+
config.action_controller.allow_forgery_protection = false
|
39
|
+
|
40
|
+
config.active_support.deprecation = :stderr
|
41
|
+
|
42
|
+
config.middleware.delete "Rack::Lock"
|
43
|
+
config.middleware.delete "ActionDispatch::Flash"
|
44
|
+
config.middleware.delete "ActionDispatch::BestStandardsSupport"
|
45
|
+
config.middleware.delete ActiveRecord::Migration::CheckPending
|
46
|
+
config.middleware.delete ActiveRecord::ConnectionAdapters::ConnectionManagement
|
47
|
+
config.middleware.delete ActiveRecord::QueryCache
|
48
|
+
config.secret_key_base = '49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk'
|
49
|
+
routes.append do
|
50
|
+
get "/" => "welcome#index"
|
51
|
+
get "/" => "fake#test"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class WelcomeController < ActionController::Base
|
57
|
+
include Rails.application.routes.url_helpers
|
58
|
+
layout 'application'
|
59
|
+
self.view_paths = [ActionView::FixtureResolver.new(
|
60
|
+
"layouts/application.html.erb" => '<%= yield %>',
|
61
|
+
"welcome/index.html.erb"=> 'Hello from index.html.erb',
|
62
|
+
)]
|
63
|
+
|
64
|
+
def index
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
Rails4::Application.initialize!
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class FakeController < ActionController::Base
|
4
|
+
include Egregious
|
5
|
+
def test
|
6
|
+
head :ok
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
#ActionDispatch::Routing::Routes.add_route('fake_page/test', :controller => 'fake_page', :action => 'test')
|
11
|
+
|
12
|
+
describe 'ShowPageModules', ' included in a ' do
|
13
|
+
describe FakeController do
|
14
|
+
|
15
|
+
it "declares a before filter that sets the variable" do
|
16
|
+
get :test
|
17
|
+
expect(assigns(:fancy_page)).to be nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/egregious_spec.rb
CHANGED
@@ -105,7 +105,7 @@ describe Egregious do
|
|
105
105
|
expect(exception_codes[Mongoid::Errors::Validations]).to eq(Egregious.status_code(:unprocessable_entity))
|
106
106
|
end
|
107
107
|
|
108
|
-
if Mongoid::VERSION > '3'
|
108
|
+
if defined?(Mongoid::VERSION) && Mongoid::VERSION > '3'
|
109
109
|
it "should return expected errors for Mongoid 3+" do
|
110
110
|
expect(exception_codes[Mongoid::Errors::ReadonlyAttribute]).to eq(Egregious.status_code(:forbidden))
|
111
111
|
expect(exception_codes[Mongoid::Errors::UnknownAttribute]).to eq(Egregious.status_code(:bad_request))
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
def rescue_from(exception, options)
|
5
|
+
end
|
6
|
+
def env
|
7
|
+
{}
|
8
|
+
end
|
9
|
+
include Egregious
|
10
|
+
|
11
|
+
describe Egregious do
|
12
|
+
|
13
|
+
context "notify_airbrake 4" do
|
14
|
+
class Airbrake
|
15
|
+
def self.notify_or_ignore(*params)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
it "should call notify_or_ignore" do
|
19
|
+
expect(Airbrake).to receive(:notify_or_ignore)
|
20
|
+
notify_airbrake(nil)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
context "notify_airbrake 5" do
|
24
|
+
class << Airbrake
|
25
|
+
remove_method :notify_or_ignore
|
26
|
+
def self.notify(*params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
it "should call notify" do
|
30
|
+
expect(Airbrake).to receive(:notify)
|
31
|
+
notify_airbrake(nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
ENV["RAILS_ENV"] ||= "test"
|
4
|
+
|
1
5
|
require 'rubygems'
|
2
6
|
require 'bundler/setup'
|
3
7
|
require 'bundler'
|
4
8
|
Bundler.setup
|
5
9
|
|
6
|
-
ENV["RAILS_ENV"] ||= "test"
|
7
10
|
require 'active_support'
|
8
|
-
require 'active_support/test_case'
|
11
|
+
#require 'active_support/test_case'
|
9
12
|
require 'action_controller'
|
10
13
|
require 'warden'
|
11
14
|
require 'cancan'
|
12
15
|
require 'mongoid'
|
13
16
|
|
14
|
-
|
17
|
+
#root = File.expand_path(File.dirname(__FILE__))
|
18
|
+
|
19
|
+
ENV["RAILS_ENV"] = "test"
|
20
|
+
require "rails"
|
21
|
+
case Rails.version
|
22
|
+
when '3.2.22'
|
23
|
+
require "apps/rails3_2"
|
24
|
+
when '4.2.5'
|
25
|
+
require "apps/rails4"
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'rspec/rails'
|
15
29
|
|
16
30
|
RSpec.configure do |config|
|
17
|
-
#
|
18
|
-
|
31
|
+
#config.rspec_opts = '--format documentation'
|
32
|
+
# The different available types are documented in the features, such as in
|
33
|
+
# https://relishapp.com/rspec/rspec-rails/docs
|
34
|
+
config.infer_spec_type_from_file_location!
|
35
|
+
end
|
36
|
+
|
37
|
+
Test::Unit::AutoRunner.need_auto_run = false if defined?(Test::Unit::AutoRunner)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: egregious
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Russell Edens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 1.
|
39
|
+
version: 1.2.5
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 1.
|
46
|
+
version: 1.2.5
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: htmlentities
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec-rails
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: json
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -143,7 +157,7 @@ dependencies:
|
|
143
157
|
- !ruby/object:Gem::Version
|
144
158
|
version: '0'
|
145
159
|
- !ruby/object:Gem::Dependency
|
146
|
-
name:
|
160
|
+
name: appraisal
|
147
161
|
requirement: !ruby/object:Gem::Requirement
|
148
162
|
requirements:
|
149
163
|
- - ">="
|
@@ -165,17 +179,25 @@ extensions: []
|
|
165
179
|
extra_rdoc_files: []
|
166
180
|
files:
|
167
181
|
- ".gitignore"
|
182
|
+
- ".travis.yml"
|
183
|
+
- Appraisals
|
168
184
|
- Gemfile
|
169
185
|
- LICENSE
|
170
|
-
- README
|
186
|
+
- README.md
|
171
187
|
- Rakefile
|
172
188
|
- egregious.gemspec
|
189
|
+
- gemfiles/rails_3.gemfile
|
190
|
+
- gemfiles/rails_4.gemfile
|
173
191
|
- lib/egregious.rb
|
174
192
|
- lib/egregious/extensions/exception.rb
|
175
193
|
- lib/egregious/extensions/mongoid.rb
|
176
194
|
- lib/egregious/version.rb
|
195
|
+
- spec/apps/rails3_2.rb
|
196
|
+
- spec/apps/rails4.rb
|
197
|
+
- spec/controllers/controller_spec.rb
|
177
198
|
- spec/egregious_spec.rb
|
178
199
|
- spec/exceptions_spec.rb
|
200
|
+
- spec/notify_airbrake_spec.rb
|
179
201
|
- spec/spec_helper.rb
|
180
202
|
homepage: http://github.com/voomify/egregious
|
181
203
|
licenses:
|
@@ -203,6 +225,10 @@ specification_version: 4
|
|
203
225
|
summary: Egregious is a rails based exception handling gem for well defined http exception
|
204
226
|
handling for json, xml and html. Requires Rails.
|
205
227
|
test_files:
|
228
|
+
- spec/apps/rails3_2.rb
|
229
|
+
- spec/apps/rails4.rb
|
230
|
+
- spec/controllers/controller_spec.rb
|
206
231
|
- spec/egregious_spec.rb
|
207
232
|
- spec/exceptions_spec.rb
|
233
|
+
- spec/notify_airbrake_spec.rb
|
208
234
|
- spec/spec_helper.rb
|
data/README
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
Update Log:
|
2
|
-
|
3
|
-
Version 0.2.10 released to https://rubygems.org/gems/egregious on 10.23.2015
|
4
|
-
Fixed bug where an exception defines http_status but returns nil.
|
5
|
-
This was resulting in a status of 200 being returned, when it should be a 500.
|
6
|
-
|
7
|
-
Version 0.2.9 released to https://rubygems.org/gems/egregious on 10.23.2015
|
8
|
-
Added support for exceptions that define a http_status. The exception map can override this.
|
9
|
-
This is a good way to allow a raise to specify a http_status using a custom exception.
|
10
|
-
The idea for this came from the Stripe::Error exception classes.
|
11
|
-
You can now use: raise Egregious::Error.new("My very bad error", :payment_required) or
|
12
|
-
define your own exceptions that implement http_status
|
13
|
-
|
14
|
-
Also updated Gemfile.lock to ruby 2.2.1 and latest dependencies. This is for specs only.
|
15
|
-
|
16
|
-
Version 0.2.8 released to https://rubygems.org/gems/egregious on 6.5.2015
|
17
|
-
Added Airbrake notifications. If this is too chatty, you can configure it by overriding: notify_airbrake
|
18
|
-
|
19
|
-
Version 0.2.7 released to https://rubygems.org/gems/egregious on 5.28.2015
|
20
|
-
Merged pull request:
|
21
|
-
Compatibility with Rails 4.2 #13
|
22
|
-
|
23
|
-
Version 0.2.6 released to https://rubygems.org/gems/egregious on 7.22.2014
|
24
|
-
Merged pull request:
|
25
|
-
Rails 4 support (#11,#12)
|
26
|
-
|
27
|
-
Version 0.2.4 released to https://rubygems.org/gems/egregious on 7.23.2013
|
28
|
-
Added MIT License
|
29
|
-
|
30
|
-
Version 0.2.3 released to https://rubygems.org/gems/egregious on 7.23.2013
|
31
|
-
Merged pull requests:
|
32
|
-
Mongoid integration (#6)
|
33
|
-
Bug Fix: Bad Rails test
|
34
|
-
Updated rails and rack dependencies
|
35
|
-
|
36
|
-
Version 0.2.2 released to https://rubygems.org/gems/egregious on 2.15.2013
|
37
|
-
Merged pull requests:
|
38
|
-
Compatibility with Rails::API (#5)
|
39
|
-
|
40
|
-
Version 0.2.1 released to https://rubygems.org/gems/egregious on 9.21.2012
|
41
|
-
Merged pull requests:
|
42
|
-
Bug Fix: should translate status code Symbol to right HTTP STATUS CODE - avinasha
|
43
|
-
Fixes teapot bug with rails 3.2.8. - kbrown
|
44
|
-
Note: version 0.2.0 does not work with rails 3.2.8 you should update to 0.2.1
|
45
|
-
|
46
|
-
If you would like to contribute take a look at the issues feature list, fork and issue a pull request!
|
47
|
-
|
48
|
-
An earlier version of these instructions with some formatting can be found @ http://railsindirection.blogspot.com/2011/09/rails-exception-handling-egregious.html
|
49
|
-
|
50
|
-
Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html.
|
51
|
-
|
52
|
-
If you have a json or xml api into your rails application, you probably have added your own exception handling to map
|
53
|
-
exceptions to a http status and formatting your json and xml output. We decided to create egregious. One of the goals
|
54
|
-
is to start providing a more consistent api error experience for all rails applications. As of the creation of
|
55
|
-
egregious the behavior of rails was to return html when an exception is thrown with the status code of 500. With
|
56
|
-
egregious proper json and html of the error will be returned with a good default mapping of exceptions to http status
|
57
|
-
codes. This allows api developers to respond to the status code properly, instead of scratching their head with 500's
|
58
|
-
coming back all the time. If the problem was the api caller then the result codes are in the 300 range. If the problem
|
59
|
-
was on the server then the status codes are in the 500 range. The returned exception message and exception type
|
60
|
-
provide the caller context information.
|
61
|
-
|
62
|
-
What egregious can do:
|
63
|
-
|
64
|
-
* Defines default exception handling for most common ruby, rails, warden, cancan and mongoid exceptions.
|
65
|
-
(warden, cancan and mongoid are optional)
|
66
|
-
* Catches defined exceptions using a rescue_with returning the status code defined for each exception
|
67
|
-
and well structured json, xml
|
68
|
-
* For html production requests attempts to load the html error pages for the mapped status code,
|
69
|
-
falling back to the 500.html page.
|
70
|
-
* Defines exceptions for all http status codes allowing you to throw these exceptions anywhere in your code.
|
71
|
-
* Allows you to change the exception mapping to fit your needs, adding exceptions and changing status mapping.
|
72
|
-
* If Hoptoad is defined it will send the errors to Hoptoad/Airbrake.
|
73
|
-
* The error will be logged with stack trace
|
74
|
-
|
75
|
-
|
76
|
-
REQUIRES:
|
77
|
-
rails ~> 3.1.12
|
78
|
-
rack >= 1.3.6
|
79
|
-
|
80
|
-
USAGE:
|
81
|
-
1) Add to your Gemfile:
|
82
|
-
gem 'egregious'
|
83
|
-
|
84
|
-
2) In your ApplicationController add:
|
85
|
-
include Egregious
|
86
|
-
|
87
|
-
Optionally, to configure create an initializer and add:
|
88
|
-
|
89
|
-
Egregious.exception_codes.merge!({NameError => :bad_request})
|
90
|
-
|
91
|
-
This will either add a new mapping or replace the existing mapping to a new status code.
|
92
|
-
You can pass the status code as a symbol, integer or string.
|
93
|
-
|
94
|
-
In your code if you want to send an error back just throw an exception. For example:
|
95
|
-
|
96
|
-
raise Egregious::BadRequest.new("You can not created an order without a customer.") unless customer_id
|
97
|
-
|
98
|
-
All the http status codes have exception classes named after them in the Egregious module. You can throw any exception,
|
99
|
-
or define your own exceptions. You can find a list in the Rack::Utils::HTTP_STATUS_CODES class.
|
100
|
-
|
101
|
-
If you want to change the behavior then you can override the following methods in your ApplicationController.
|
102
|
-
|
103
|
-
# override this if you want your flash to behave differently
|
104
|
-
def egregious_flash(exception)
|
105
|
-
flash.now[:alert] = exception.message
|
106
|
-
end
|
107
|
-
|
108
|
-
# override this if you want your logging to behave differently
|
109
|
-
def egregious_log(exception)
|
110
|
-
logger.fatal(
|
111
|
-
"\n\n" + exception.class.to_s + ' (' + exception.message.to_s + '):\n ' +
|
112
|
-
clean_backtrace(exception).join("\n ") +
|
113
|
-
"\n\n")
|
114
|
-
HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
|
115
|
-
end
|
116
|
-
|
117
|
-
# override this if you want to change your respond_to behavior
|
118
|
-
def egregious_respond_to(exception)
|
119
|
-
respond_to do |format|
|
120
|
-
status = status_code_for_exception(exception)
|
121
|
-
format.xml { render :xml=> exception.to_xml, :status => status }
|
122
|
-
format.json { render :json=> exception.to_json, :status => status }
|
123
|
-
# render the html page for the status we are returning it exists...if not then render the 500.html page.
|
124
|
-
format.html { render :file => File.exists?(build_html_file_path(status)) ?
|
125
|
-
build_html_file_path(status) : build_html_file_path('500')}
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# override this if you want to change what html static file gets returned.
|
132
|
-
def build_html_file_path(status)
|
133
|
-
File.expand_path(Rails.root, 'public', status + '.html')
|
134
|
-
end
|
135
|
-
|
136
|
-
# override this if you want to control what gets sent to airbrake
|
137
|
-
# optionally you can configure the airbrake ignore list
|
138
|
-
def notify_airbrake(exception)
|
139
|
-
# for ancient clients - can probably remove
|
140
|
-
HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
|
141
|
-
# tested with airbrake 3.1.15 and 4.2.1
|
142
|
-
env['airbrake.error_id'] = Airbrake.notify_or_ignore(exception) if defined?(Airbrake)
|
143
|
-
end
|
144
|
-
|
145
|
-
KNOWN ISSUES:
|
146
|
-
* If you use Mongoid, CanCan or Devise you must have Egregious after CanCan/Devise in your Gemfile, if not it will not handle those errors correctly.
|