egregious 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|