nested_exceptions 1.0.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 +6 -0
- data/.rspec +0 -0
- data/Gemfile +4 -0
- data/Rakefile +17 -0
- data/lib/nested_exceptions/define.rb +23 -0
- data/lib/nested_exceptions/global.rb +7 -0
- data/lib/nested_exceptions/version.rb +11 -0
- data/lib/nested_exceptions.rb +50 -0
- data/nested_exceptions.gemspec +21 -0
- data/spec/nested_exceptions_spec.rb +96 -0
- data/spec/spec_helper.rb +2 -0
- metadata +92 -0
data/.gitignore
ADDED
data/.rspec
ADDED
File without changes
|
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
6
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
10
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
11
|
+
spec.ruby_opts = '--debug'
|
12
|
+
spec.skip_bundler = true
|
13
|
+
spec.rcov = true
|
14
|
+
spec.rcov_opts = %w{--exclude generator_internal,jsignal_internal,gems\/,spec\/}
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => :spec
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module NestedExceptions
|
2
|
+
class << self
|
3
|
+
# Define a set of standard exception classes as recommended in
|
4
|
+
# http://exceptionalruby.com/
|
5
|
+
#
|
6
|
+
# I actually recommend that you just define these manually, but this may be
|
7
|
+
# a handy shortcut in smaller projects.
|
8
|
+
def define_standard_exception_classes_in(target_module)
|
9
|
+
definitions = %{
|
10
|
+
class Error < StandardError; include NestedExceptions; end
|
11
|
+
class UserError < Error; end
|
12
|
+
class LogicError < Error; end
|
13
|
+
class ClientError < LogicError; end
|
14
|
+
class InternalError < LogicError; end
|
15
|
+
class TransientError < Error; end
|
16
|
+
}
|
17
|
+
target_module.module_eval definitions
|
18
|
+
[:Error, :UserError, :LogicError, :ClientError, :InternalError, :TransientError].map do |name|
|
19
|
+
target_module.const_get name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "nested_exceptions/version"
|
2
|
+
require "nested_exceptions/define"
|
3
|
+
|
4
|
+
# Just include this module in your custom exception class
|
5
|
+
module NestedExceptions
|
6
|
+
attr_reader :cause
|
7
|
+
|
8
|
+
def initialize(message = nil, cause = nil)
|
9
|
+
@cause = cause || $!
|
10
|
+
super(message)
|
11
|
+
end
|
12
|
+
|
13
|
+
if Object.const_defined? :RUBY_ENGINE and RUBY_ENGINE == 'jruby' or RUBY_ENGINE == 'rbx'
|
14
|
+
def backtrace
|
15
|
+
return @processed_backtrace if defined? @processed_backtrace and @processed_backtrace
|
16
|
+
@processed_backtrace = process_backtrace(super)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
def set_backtrace(bt)
|
20
|
+
super process_backtrace(bt)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def root_cause
|
25
|
+
rc = e = self
|
26
|
+
while e
|
27
|
+
rc = e
|
28
|
+
break unless e.respond_to? :cause
|
29
|
+
e = e.cause
|
30
|
+
end
|
31
|
+
rc
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def process_backtrace(bt)
|
37
|
+
if cause
|
38
|
+
cause.backtrace.reverse.each do |line|
|
39
|
+
if bt.last == line
|
40
|
+
bt.pop
|
41
|
+
else
|
42
|
+
break
|
43
|
+
end
|
44
|
+
end
|
45
|
+
bt << "--- cause: #{cause.class.name}: #{cause}"
|
46
|
+
bt.concat cause.backtrace
|
47
|
+
end
|
48
|
+
bt
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "nested_exceptions/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "nested_exceptions"
|
7
|
+
s.version = NestedExceptions::VERSION
|
8
|
+
s.authors = ["Darrick Wiebe"]
|
9
|
+
s.email = ["dw@xnlogic.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Support nested exceptions in all rubies}
|
12
|
+
s.description = %q{Based on ideas in http://exceptionalruby.com/ and the nestegg gem which does not support JRuby.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "nested_exceptions"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ErrorSpec
|
4
|
+
|
5
|
+
NestedExceptions.define_standard_exception_classes_in ErrorSpec
|
6
|
+
|
7
|
+
class Example
|
8
|
+
def bug
|
9
|
+
raise 'bug'
|
10
|
+
end
|
11
|
+
|
12
|
+
def nested_bug
|
13
|
+
bug
|
14
|
+
end
|
15
|
+
|
16
|
+
def problem
|
17
|
+
nested_bug
|
18
|
+
rescue
|
19
|
+
raise InternalError, 'problem'
|
20
|
+
end
|
21
|
+
|
22
|
+
def nested_problem
|
23
|
+
problem
|
24
|
+
end
|
25
|
+
|
26
|
+
def double_bug
|
27
|
+
nested_problem
|
28
|
+
rescue
|
29
|
+
raise 'oops'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe NestedExceptions do
|
35
|
+
let(:ex) { ErrorSpec::Example.new }
|
36
|
+
def in_rescue
|
37
|
+
if Object.const_defined? :RUBY_ENGINE and RUBY_ENGINE == 'jruby'
|
38
|
+
''
|
39
|
+
elsif RUBY_VERSION =~ /^1\.[0-8]\./
|
40
|
+
''
|
41
|
+
else
|
42
|
+
in_rescue = 'rescue in '
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should create a stack trace correctly' do
|
47
|
+
stack = raise rescue $!.backtrace
|
48
|
+
stack.first.should =~ /#{__FILE__}:#{__LINE__ - 1}/
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'normal StandardError' do
|
52
|
+
subject do
|
53
|
+
@stack = raise rescue $!.backtrace; ex.bug rescue $!
|
54
|
+
end
|
55
|
+
its(:message) { should == 'bug' }
|
56
|
+
its(:backtrace) { should == ["#{__FILE__}:9:in `bug'"] + @stack }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'nested InternalError' do
|
60
|
+
subject do
|
61
|
+
@stack = raise rescue $!.backtrace; ex.problem rescue $!
|
62
|
+
end
|
63
|
+
its(:message) { should == 'problem' }
|
64
|
+
its('root_cause.message') { should == 'bug' }
|
65
|
+
its(:backtrace) do
|
66
|
+
should == [
|
67
|
+
"#{__FILE__}:19:in `#{in_rescue}problem'",
|
68
|
+
"--- cause: RuntimeError: bug",
|
69
|
+
"#{__FILE__}:9:in `bug'",
|
70
|
+
"#{__FILE__}:13:in `nested_bug'",
|
71
|
+
"#{__FILE__}:17:in `problem'"
|
72
|
+
] + @stack
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'double nested StandardError' do
|
77
|
+
subject do
|
78
|
+
@stack = raise rescue $!.backtrace; ex.double_bug rescue $!
|
79
|
+
end
|
80
|
+
its(:message) { should == 'oops' }
|
81
|
+
its('root_cause.message') { should == 'bug' }
|
82
|
+
its(:backtrace) do
|
83
|
+
should == [
|
84
|
+
"#{__FILE__}:29:in `#{in_rescue}double_bug'",
|
85
|
+
"--- cause: ErrorSpec::InternalError: problem",
|
86
|
+
"#{__FILE__}:19:in `#{in_rescue}problem'",
|
87
|
+
"--- cause: RuntimeError: bug",
|
88
|
+
"#{__FILE__}:9:in `bug'",
|
89
|
+
"#{__FILE__}:13:in `nested_bug'",
|
90
|
+
"#{__FILE__}:17:in `problem'",
|
91
|
+
"#{__FILE__}:23:in `nested_problem'",
|
92
|
+
"#{__FILE__}:27:in `double_bug'"
|
93
|
+
] + @stack
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nested_exceptions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 2387456872237229630
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Darrick Wiebe
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-21 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: 2002549777813010636
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Based on ideas in http://exceptionalruby.com/ and the nestegg gem which does not support JRuby.
|
36
|
+
email:
|
37
|
+
- dw@xnlogic.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- .rspec
|
47
|
+
- Gemfile
|
48
|
+
- Rakefile
|
49
|
+
- lib/nested_exceptions.rb
|
50
|
+
- lib/nested_exceptions/define.rb
|
51
|
+
- lib/nested_exceptions/global.rb
|
52
|
+
- lib/nested_exceptions/version.rb
|
53
|
+
- nested_exceptions.gemspec
|
54
|
+
- spec/nested_exceptions_spec.rb
|
55
|
+
- spec/spec_helper.rb
|
56
|
+
has_rdoc: true
|
57
|
+
homepage: ""
|
58
|
+
licenses: []
|
59
|
+
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 2002549777813010636
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 2002549777813010636
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project: nested_exceptions
|
86
|
+
rubygems_version: 1.5.2
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Support nested exceptions in all rubies
|
90
|
+
test_files:
|
91
|
+
- spec/nested_exceptions_spec.rb
|
92
|
+
- spec/spec_helper.rb
|