egregious 0.2.10 → 0.2.12
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/.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
|
+
[](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.
|