egregious 0.1.0
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.
- data/.gitignore +5 -0
- data/Gemfile +5 -0
- data/README +47 -0
- data/Rakefile +1 -0
- data/egregious.gemspec +31 -0
- data/lib/egregious.rb +159 -0
- data/lib/egregious/extensions/exception.rb +17 -0
- data/lib/egregious/version.rb +3 -0
- data/spec/egregious_spec.rb +105 -0
- data/spec/exceptions_spec.rb +29 -0
- data/spec/spec_helper.rb +16 -0
- metadata +195 -0
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html.
|
2
|
+
|
3
|
+
If you have a json or xml api into your rails application, you probably have added your own exception handling to map
|
4
|
+
exceptions to a http status and formatting your json and xml output. We did to. We were tired of doing it over and
|
5
|
+
over. We decided to create egregious. One of the major goals is to start providing a more consistent api error
|
6
|
+
experience for all rails applications. As of the creation of egregious the behavior of rails was to return html when an
|
7
|
+
exception is thrown with the status code of 500. With egregious proper json and html of the error will be returned
|
8
|
+
with a good default mapping of exceptions to http status codes. This allows api developers to respond to the status
|
9
|
+
code properly, instead of scratching their head with 500's coming back all the time. If the problem was yours then the
|
10
|
+
result codes are in the 300 range. If the problem was the server then the status codes are in the 500's. With the
|
11
|
+
message and exception type providing more context information.
|
12
|
+
|
13
|
+
What egregious can do:
|
14
|
+
|
15
|
+
* Defines default exception handling for most common ruby, rails, warden and cancan exceptions.
|
16
|
+
(warden and cancan are optional)
|
17
|
+
* Catches defined exceptions using a rescue_with returning the status code defined for each exception
|
18
|
+
and well structured json, xml
|
19
|
+
* For html production requests attempts to load the html error pages for the mapped status code,
|
20
|
+
falling back to the 500.html page.
|
21
|
+
* Defines exceptions for all http status codes allowing you to throw these exceptions anywhere in your code.
|
22
|
+
* Allows you to change the exception mapping to fit your needs, adding exceptions and changing status mapping.
|
23
|
+
|
24
|
+
|
25
|
+
REQUIRES:
|
26
|
+
Rails 3.x
|
27
|
+
|
28
|
+
USAGE:
|
29
|
+
1) Add to your Gemfile:
|
30
|
+
gem 'egregious'
|
31
|
+
|
32
|
+
2) In your ApplicationController add:
|
33
|
+
include Egregious
|
34
|
+
|
35
|
+
Optionally, to configure create an initializer and add:
|
36
|
+
|
37
|
+
Egregious.exception_codes.merge!({NameError => :bad_request})
|
38
|
+
|
39
|
+
This will either add a new mapping or replace the existing mapping to a new status code.
|
40
|
+
You can pass the status code as a symbol, integer or string.
|
41
|
+
|
42
|
+
In your code if you want to send an error back just throw an exception. For example:
|
43
|
+
|
44
|
+
raise Egregious::BadRequest.new("You can not created an order without a customer.") unless customer_id
|
45
|
+
|
46
|
+
All the http status codes have exception classes named after them in the Egregious module. You can throw any exception,
|
47
|
+
or define your own exceptions. You can find a list in the Rack::Utils::HTTP_STATUS_CODES class.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/egregious.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "egregious/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "egregious"
|
7
|
+
s.version = Egregious::VERSION
|
8
|
+
s.authors = ["Russell Edens"]
|
9
|
+
s.email = ["rx@voomify.com"]
|
10
|
+
s.homepage = "http://github.com/voomify/egregious"
|
11
|
+
s.summary = %q{Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html}
|
12
|
+
s.description = %q{Requires Rails 3.x.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "egregious"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency "json"
|
24
|
+
s.add_development_dependency "hpricot"
|
25
|
+
s.add_development_dependency "rails", '~> 3.1.0'
|
26
|
+
s.add_development_dependency "rails", '~> 3.1.0'
|
27
|
+
s.add_development_dependency "warden"
|
28
|
+
s.add_development_dependency "cancan"
|
29
|
+
|
30
|
+
s.add_runtime_dependency "rack"
|
31
|
+
end
|
data/lib/egregious.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require "egregious/version"
|
2
|
+
require "egregious/extensions/exception"
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
|
6
|
+
module Egregious
|
7
|
+
|
8
|
+
# use these exception to control the code you are throwing from you code
|
9
|
+
# all http statuses have an exception defined for them
|
10
|
+
Rack::Utils::HTTP_STATUS_CODES.each do |key, value|
|
11
|
+
class_eval "class #{value.gsub(/\s|-/,'')} < StandardError; end"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.status_code(status)
|
15
|
+
if status.is_a?(Symbol)
|
16
|
+
Rack::Utils::HTTP_STATUS_CODES[status] || 500
|
17
|
+
else
|
18
|
+
status.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# internal method that loads the exception codes
|
23
|
+
def self._load_exception_codes
|
24
|
+
|
25
|
+
# by default if there is not mapping they map to 500/internal server error
|
26
|
+
exception_codes = {
|
27
|
+
SecurityError=>status_code(:forbidden)
|
28
|
+
}
|
29
|
+
# all status codes have a exception class defined
|
30
|
+
Rack::Utils::HTTP_STATUS_CODES.each do |key, value|
|
31
|
+
exception_codes.merge!(eval("Egregious::#{value.gsub(/\s|-/,'')}")=>value.downcase.gsub(/\s|-/, '_').to_sym)
|
32
|
+
end
|
33
|
+
|
34
|
+
if defined?(ActionController)
|
35
|
+
exception_codes.merge!({
|
36
|
+
AbstractController::ActionNotFound=>status_code(:bad_request),
|
37
|
+
ActionController::InvalidAuthenticityToken=>status_code(:bad_request),
|
38
|
+
ActionController::MethodNotAllowed=>status_code(:not_allowed),
|
39
|
+
ActionController::MissingFile=>status_code(:not_found),
|
40
|
+
ActionController::RoutingError=>status_code(:bad_request),
|
41
|
+
ActionController::UnknownController=>status_code(:bad_request),
|
42
|
+
ActionController::UnknownHttpMethod=>status_code(:not_allowed)
|
43
|
+
#ActionController::MissingTemplate=>status_code(:not_found)
|
44
|
+
})
|
45
|
+
end
|
46
|
+
|
47
|
+
if defined?(ActiveModel)
|
48
|
+
exception_codes.merge!({
|
49
|
+
ActiveModel::MissingAttributeError=>status_code(:bad_request)})
|
50
|
+
end
|
51
|
+
|
52
|
+
if defined?(ActiveRecord)
|
53
|
+
exception_codes.merge!({
|
54
|
+
ActiveRecord::AttributeAssignmentError=>status_code(:bad_request),
|
55
|
+
ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded=>status_code(:bad_request),
|
56
|
+
ActiveRecord::MultiparameterAssignmentErrors=>status_code(:bad_request),
|
57
|
+
ActiveRecord::ReadOnlyAssociation=>status_code(:forbidden),
|
58
|
+
ActiveRecord::ReadOnlyRecord=>status_code(:forbidden),
|
59
|
+
ActiveRecord::RecordInvalid=>status_code(:bad_request),
|
60
|
+
ActiveRecord::RecordNotFound=>status_code(:not_found),
|
61
|
+
ActiveRecord::UnknownAttributeError=>status_code(:bad_request)
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
if defined?(Warden)
|
66
|
+
exception_codes.merge!({
|
67
|
+
Warden::NotAuthenticated=>status_code(:unauthorized),
|
68
|
+
})
|
69
|
+
end
|
70
|
+
|
71
|
+
if defined?(CanCan)
|
72
|
+
# technically this should be forbidden, but for some reason cancan returns AccessDenied when you are not logged in
|
73
|
+
exception_codes.merge!({CanCan::AccessDenied=>status_code(:unauthorized)})
|
74
|
+
exception_codes.merge!({CanCan::AuthorizationNotPerformed => status_code(:unauthorized)})
|
75
|
+
end
|
76
|
+
|
77
|
+
@@exception_codes = exception_codes
|
78
|
+
end
|
79
|
+
|
80
|
+
@@exception_codes = self._load_exception_codes
|
81
|
+
@@root = defined?(Rail) ? Rails.root : nil
|
82
|
+
|
83
|
+
# exposes the root of the app
|
84
|
+
def self.root
|
85
|
+
@@root
|
86
|
+
end
|
87
|
+
|
88
|
+
# set the root directory and stack traces will be cleaned up
|
89
|
+
def self.root=(root)
|
90
|
+
@@root=root
|
91
|
+
end
|
92
|
+
|
93
|
+
# a little helper to help us clean up the backtrace
|
94
|
+
# if root is defined it removes that, for rails it takes care of that
|
95
|
+
def clean_backtrace(exception)
|
96
|
+
if backtrace = exception.backtrace
|
97
|
+
if Egregious.root
|
98
|
+
backtrace.map { |line| line.sub Egregious.root, '' }
|
99
|
+
else
|
100
|
+
backtrace
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# this method exposes the @@exception_codes class variable
|
106
|
+
# allowing someone to re-configure the mapping. For example in a rails initializer:
|
107
|
+
# Egregious.exception_codes = {NameError => "503"} or
|
108
|
+
# If you want the default mapping and then want to modify it you should call the following:
|
109
|
+
# Egregious.exception_codes.merge!({MyCustomException=>"500"})
|
110
|
+
def self.exception_codes
|
111
|
+
@@exception_codes
|
112
|
+
end
|
113
|
+
|
114
|
+
# this method exposes the @@exception_codes class variable
|
115
|
+
# allowing someone to re-configure the mapping. For example in a rails initializer:
|
116
|
+
# Egregious.exception_codes = {NameError => "503"} or
|
117
|
+
# If you want the default mapping and then want to modify it you should call the following:
|
118
|
+
# Egregious.exception_codes.merge!({MyCustomException=>"500"})
|
119
|
+
def self.exception_codes=(exception_codes)
|
120
|
+
@@exception_codes=exception_codes
|
121
|
+
end
|
122
|
+
|
123
|
+
# this method will auto load the exception codes if they are not set
|
124
|
+
# by an external configuration call to self.exception_code already
|
125
|
+
# it is called by the status_code_for_exception method
|
126
|
+
def exception_codes
|
127
|
+
return Egregious.exception_codes
|
128
|
+
end
|
129
|
+
|
130
|
+
# this method will lookup the exception code for a given exception class
|
131
|
+
# if the exception is not in our map then it will return 500
|
132
|
+
def status_code_for_exception(exception)
|
133
|
+
self.exception_codes[exception.class] ? self.exception_codes[exception.class] : '500'
|
134
|
+
end
|
135
|
+
|
136
|
+
def egregious_exception_handler(exception)
|
137
|
+
flash.now[:alert] = exception.message
|
138
|
+
logger.fatal(
|
139
|
+
"\n\n" + exception.class.to_s + ' (' + exception.message.to_s + '):\n ' +
|
140
|
+
clean_backtrace(exception).join("\n ") +
|
141
|
+
"\n\n")
|
142
|
+
HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
|
143
|
+
respond_to do |format|
|
144
|
+
status = status_code_for_exception(exception)
|
145
|
+
format.xml { render :xml=> exception.to_xml, :status => status }
|
146
|
+
format.json { render :json=> exception.to_json, :status => status }
|
147
|
+
# render the html page for the status we are returning it exists...if not then render the 500.html page.
|
148
|
+
format.html { render :file => File.exists?(Rails.root + '/public/' + status + '.html') ?
|
149
|
+
Rails.root + '/public/' + status + '.html' : Rails.root + '/public/500.html'}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def self.included(base)
|
155
|
+
base.class_eval do
|
156
|
+
rescue_from 'Exception' , :with => :egregious_exception_handler
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#
|
2
|
+
# We are opening up Exception and adding to_xml and to_json.
|
3
|
+
#
|
4
|
+
class Exception
|
5
|
+
|
6
|
+
def exception_type
|
7
|
+
self.class.to_s ? self.class.to_s.split("::").last : 'None'
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_xml
|
11
|
+
"<errors><error>#{self.message}</error><type>#{self.exception_type}</type></errors>"
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json
|
15
|
+
"{\"error\":\"#{self.message.gsub(/\r/, ' ').gsub(/\n/, ' ').squeeze(' ')}\", \"type\":\"#{self.exception_type}\"}"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def rescue_from(exception, options)
|
4
|
+
end
|
5
|
+
|
6
|
+
include Egregious
|
7
|
+
|
8
|
+
describe Egregious do
|
9
|
+
describe 'clean_backtrace ' do
|
10
|
+
it "should return nil" do
|
11
|
+
clean_backtrace(Exception.new).should == nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return a stack trace" do
|
15
|
+
begin
|
16
|
+
raise Exception.new
|
17
|
+
rescue Exception=>exception
|
18
|
+
clean_backtrace(exception).size.should be > 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should remove the beginning of the backtrace" do
|
23
|
+
begin
|
24
|
+
raise Exception.new
|
25
|
+
rescue Exception=>exception
|
26
|
+
class Rails
|
27
|
+
def self.root
|
28
|
+
__FILE__
|
29
|
+
end
|
30
|
+
end
|
31
|
+
clean_backtrace(exception)[0].should match /:\d/
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Once these codes are published and used in the gem, they should not change.
|
38
|
+
# it will break other peoples apis. This test ensures that.
|
39
|
+
# client should use a configuration file to change the mappings themselves
|
40
|
+
#
|
41
|
+
describe 'exception_codes' do
|
42
|
+
|
43
|
+
it "should return forbidden for SecurityError's'" do
|
44
|
+
exception_codes[SecurityError].should == Egregious.status_code(:forbidden)
|
45
|
+
end
|
46
|
+
|
47
|
+
if defined?(ActionController)
|
48
|
+
it "should return expected errors for ActionController" do
|
49
|
+
exception_codes[AbstractController::ActionNotFound].should == Egregious.status_code(:forbidden)
|
50
|
+
exception_codes[AbstractController::ActionNotFound].should == Egregious.status_code(:bad_request)
|
51
|
+
exception_codes[ActionController::InvalidAuthenticityToken].should == Egregious.status_code(:bad_request)
|
52
|
+
exception_codes[ActionController::MethodNotAllowed].should == Egregious.status_code(:not_allowed)
|
53
|
+
exception_codes[ActionController::MissingFile].should == Egregious.status_code(:not_found)
|
54
|
+
exception_codes[ActionController::RoutingError].should == Egregious.status_code(:bad_request)
|
55
|
+
exception_codes[ActionController::UnknownController].should == Egregious.status_code(:bad_request)
|
56
|
+
exception_codes[ActionController::UnknownHttpMethod].should == Egregious.status_code(:not_allowed)
|
57
|
+
exception_codes[ActionController::MissingTemplate].should == Egregious.status_code(:not_found)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if defined?(ActiveModel)
|
62
|
+
it "should return expected errors for ActiveModel" do
|
63
|
+
exception_codes[ActiveModel::MissingAttributeError].should == Egregious.status_code(:bad_request)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if defined?(ActiveRecord)
|
68
|
+
it "should return expected errors for ActiveRecord" do
|
69
|
+
exception_codes[ActiveRecord::AttributeAssignmentError].should == Egregious.status_code(:bad_request)
|
70
|
+
exception_codes[ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded].should == Egregious.status_code(:bad_request)
|
71
|
+
exception_codes[ActiveRecord::MultiparameterAssignmentErrors].should == Egregious.status_code(:bad_request)
|
72
|
+
exception_codes[ActiveRecord::ReadOnlyAssociation].should == Egregious.status_code(:forbidden)
|
73
|
+
exception_codes[ActiveRecord::ReadOnlyRecord].should == Egregious.status_code(:forbidden)
|
74
|
+
exception_codes[ActiveRecord::RecordInvalid].should == Egregious.status_code(:bad_request)
|
75
|
+
exception_codes[ActiveRecord::RecordNotFound].should == Egregious.status_code(:not_found)
|
76
|
+
exception_codes[ActiveRecord::UnknownAttributeError].should == Egregious.status_code(:bad_request)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if defined?(Warden)
|
81
|
+
it "should return expected errors for Warden" do
|
82
|
+
exception_codes[Warden::NotAuthenticated].should == Egregious.status_code(:unauthorized)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if defined?(CanCan)
|
87
|
+
it "should return expected errors for CanCan" do
|
88
|
+
# technically this should be forbidden, but for some reason cancan returns AccessDenied when you are not logged in
|
89
|
+
exception_codes[CanCan::AccessDenied].should == Egregious.status_code(:unauthorized)
|
90
|
+
exception_codes[CanCan::AuthorizationNotPerformed].should == Egregious.status_code(:unauthorized)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "status_code_for_exception" do
|
96
|
+
it 'should return 500 for non-mapped exceptions'do
|
97
|
+
exception_codes[Exception].should == nil
|
98
|
+
status_code_for_exception(Exception.new).should=='500'
|
99
|
+
end
|
100
|
+
it 'should allow configuration of exception codes' do
|
101
|
+
Egregious.exception_codes.merge!({NameError => "999"})
|
102
|
+
status_code_for_exception(NameError.new).should=="999"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
require 'hpricot'
|
4
|
+
|
5
|
+
describe Exception do
|
6
|
+
it "should output valid xml on to_xml" do
|
7
|
+
doc = Hpricot.XML(Exception.new("Yes").to_xml)
|
8
|
+
(doc/:errors).each do |error|
|
9
|
+
(error/:error).inner_html.should=='Yes'
|
10
|
+
(error/:type).inner_html.should=='Exception'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should output be valid json on to_json" do
|
15
|
+
result = JSON.parse(Exception.new("Yes").to_json)
|
16
|
+
result['error'].should == "Yes"
|
17
|
+
result['type'].should == "Exception"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should parse module names out" do
|
21
|
+
module X
|
22
|
+
module Y
|
23
|
+
class Z < Exception
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
X::Y::Z.new.exception_type.should == 'Z'
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup
|
5
|
+
|
6
|
+
ENV["RAILS_ENV"] ||= "test"
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_support/test_case'
|
9
|
+
require 'warden'
|
10
|
+
require 'cancan'
|
11
|
+
|
12
|
+
require 'egregious' # and any other gems you need
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
# some (optional) config here
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: egregious
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Russell Edens
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-27 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: json
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: hpricot
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rails
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 3
|
74
|
+
- 1
|
75
|
+
- 0
|
76
|
+
version: 3.1.0
|
77
|
+
type: :development
|
78
|
+
version_requirements: *id004
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: rails
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 3
|
90
|
+
- 1
|
91
|
+
- 0
|
92
|
+
version: 3.1.0
|
93
|
+
type: :development
|
94
|
+
version_requirements: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: warden
|
97
|
+
prerelease: false
|
98
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
type: :development
|
108
|
+
version_requirements: *id006
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: cancan
|
111
|
+
prerelease: false
|
112
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
type: :development
|
122
|
+
version_requirements: *id007
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: rack
|
125
|
+
prerelease: false
|
126
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
hash: 3
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
version: "0"
|
135
|
+
type: :runtime
|
136
|
+
version_requirements: *id008
|
137
|
+
description: Requires Rails 3.x.
|
138
|
+
email:
|
139
|
+
- rx@voomify.com
|
140
|
+
executables: []
|
141
|
+
|
142
|
+
extensions: []
|
143
|
+
|
144
|
+
extra_rdoc_files: []
|
145
|
+
|
146
|
+
files:
|
147
|
+
- .gitignore
|
148
|
+
- Gemfile
|
149
|
+
- README
|
150
|
+
- Rakefile
|
151
|
+
- egregious.gemspec
|
152
|
+
- lib/egregious.rb
|
153
|
+
- lib/egregious/extensions/exception.rb
|
154
|
+
- lib/egregious/version.rb
|
155
|
+
- spec/egregious_spec.rb
|
156
|
+
- spec/exceptions_spec.rb
|
157
|
+
- spec/spec_helper.rb
|
158
|
+
has_rdoc: true
|
159
|
+
homepage: http://github.com/voomify/egregious
|
160
|
+
licenses: []
|
161
|
+
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
hash: 3
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
version: "0"
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
hash: 3
|
182
|
+
segments:
|
183
|
+
- 0
|
184
|
+
version: "0"
|
185
|
+
requirements: []
|
186
|
+
|
187
|
+
rubyforge_project: egregious
|
188
|
+
rubygems_version: 1.5.2
|
189
|
+
signing_key:
|
190
|
+
specification_version: 3
|
191
|
+
summary: Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html
|
192
|
+
test_files:
|
193
|
+
- spec/egregious_spec.rb
|
194
|
+
- spec/exceptions_spec.rb
|
195
|
+
- spec/spec_helper.rb
|