absolver 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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/README.md +59 -0
- data/Rakefile +15 -0
- data/absolver.gemspec +21 -0
- data/lib/absolver.rb +38 -0
- data/lib/absolver/exception.rb +7 -0
- data/lib/absolver/version.rb +3 -0
- data/spec/absolver_spec.rb +22 -0
- data/spec/exception_spec.rb +22 -0
- data/spec/spec_helper.rb +8 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c76e2d96ca20824c08be83d405a482c3868f17f734d7bd8bde2c167b7da5595a
|
4
|
+
data.tar.gz: cddc7a5991121d3bcdfddfde761399211df4f4410860e3a9b6b04b45ae597d11
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0d38a00d96c571ce019ace9a2a21145ed8c390d932f71aebfcaea9d191602542732515fafd9baed186cc72f74c8ba66ce23562db75b6b591f0346bd24cc2cdd9
|
7
|
+
data.tar.gz: b5e418beeb6af4ed83c1582cfcf2d3723b6761d8be8df0094a48111cc94fc4c408d20042c94cd5bcb3bdc81cc8016b6da32e7b266f60d5eec9367c65560487de
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
absolver
|
2
|
+
===
|
3
|
+
|
4
|
+
Absolver is a small little gem that allows setting the cause of a Ruby exception. Consider this example:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
err = begin
|
8
|
+
begin
|
9
|
+
1 / 0
|
10
|
+
rescue => e
|
11
|
+
raise RuntimeError, 'foo'
|
12
|
+
end
|
13
|
+
rescue => e
|
14
|
+
e
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
Notice that I raised a `RuntimeError` _inside_ a `rescue` block. In Ruby 2.1 and later, doing so will set the inner exception's `#cause` attribute to the outer exception. In other words:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
err # => #<RuntimeError: foo>
|
22
|
+
err.cause # => #<ZeroDivisionError: divided by 0>
|
23
|
+
```
|
24
|
+
|
25
|
+
Cool, thanks Ruby!
|
26
|
+
|
27
|
+
What if I want to change the cause though? Maybe I don't really want to include the cause when reporting to an external error monitoring service, for example. Sadly, Ruby doesn't let you do that:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
err.cause = nil
|
31
|
+
# NoMethodError (undefined method `cause=' for #<RuntimeError: foo>)
|
32
|
+
```
|
33
|
+
|
34
|
+
What's a programmer to do? Use absolver!
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'absolver'
|
38
|
+
|
39
|
+
Absolver.set_cause(err, nil)
|
40
|
+
|
41
|
+
err.cause # => nil
|
42
|
+
```
|
43
|
+
|
44
|
+
Absolver uses [Fiddle](https://ruby-doc.org/stdlib-2.5.0/libdoc/fiddle/rdoc/Fiddle.html) to safely set the `cause` attribute of the `Exception` object. Basically it reaches down into Ruby's internals to adjust the value of the `cause` instance variable, which normally isn't exposed to your program.
|
45
|
+
|
46
|
+
Absolver also includes a small monkeypatch that adds `cause=` to `Exception`. Because many people dislike monkeypatches, you have to opt-in:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'absolver/exception'
|
50
|
+
err.cause = nil
|
51
|
+
```
|
52
|
+
|
53
|
+
## License
|
54
|
+
|
55
|
+
Licensed under the MIT license. See LICENSE for details.
|
56
|
+
|
57
|
+
## Authors
|
58
|
+
|
59
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'rubygems/package_task'
|
6
|
+
require 'absolver'
|
7
|
+
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
task default: :spec
|
11
|
+
|
12
|
+
desc 'Run specs'
|
13
|
+
RSpec::Core::RakeTask.new do |t|
|
14
|
+
t.pattern = './spec/**/*_spec.rb'
|
15
|
+
end
|
data/absolver.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'absolver/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'absolver'
|
6
|
+
s.version = ::Absolver::VERSION
|
7
|
+
s.authors = ['Cameron Dutro']
|
8
|
+
s.email = ['camertron@gmail.com']
|
9
|
+
s.homepage = 'http://github.com/camertron/absolver'
|
10
|
+
|
11
|
+
s.description = s.summary = 'Allows setting the cause of Ruby exceptions.'
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.has_rdoc = true
|
15
|
+
|
16
|
+
s.add_development_dependency 'rake'
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
|
19
|
+
s.require_path = 'lib'
|
20
|
+
s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'README.md', 'Rakefile', 'absolver.gemspec']
|
21
|
+
end
|
data/lib/absolver.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'fiddle'
|
2
|
+
|
3
|
+
module Absolver
|
4
|
+
class << self
|
5
|
+
def set_cause(exc, new_cause)
|
6
|
+
rb_ivar_set(exc, 'cause', new_cause)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def rb_ivar_set(mod, str, new_val)
|
12
|
+
id = rb_intern_str(str)
|
13
|
+
m = Fiddle.dlwrap(mod)
|
14
|
+
nv = Fiddle.dlwrap(new_val)
|
15
|
+
Fiddle.dlunwrap(rb_ivar_set_func.call(m, id, nv))
|
16
|
+
end
|
17
|
+
|
18
|
+
def rb_ivar_set_func
|
19
|
+
@rb_ivar_set_func ||= Fiddle::Function.new(
|
20
|
+
Fiddle::Handle::DEFAULT['rb_ivar_set'],
|
21
|
+
[Fiddle::TYPE_VOIDP] * 3, # arguments
|
22
|
+
Fiddle::TYPE_VOIDP # return type
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def rb_intern_str(str)
|
27
|
+
rb_intern_str_func.call(Fiddle.dlwrap(str))
|
28
|
+
end
|
29
|
+
|
30
|
+
def rb_intern_str_func
|
31
|
+
@rb_intern_str_func ||= Fiddle::Function.new(
|
32
|
+
Fiddle::Handle::DEFAULT['rb_intern_str'],
|
33
|
+
[Fiddle::TYPE_VOIDP], # arguments
|
34
|
+
Fiddle::TYPE_VOIDP # return type
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Absolver do
|
4
|
+
describe '.set_cause' do
|
5
|
+
let(:exc) { begin; 1 / 0; rescue => e; e; end }
|
6
|
+
let(:cause) { RuntimeError.new('foobar') }
|
7
|
+
|
8
|
+
it 'sets the cause on an exception' do
|
9
|
+
expect { Absolver.set_cause(exc, cause) }.to(
|
10
|
+
change { exc.cause }.from(nil).to(cause)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows the cause to be set to nil' do
|
15
|
+
Absolver.set_cause(exc, cause)
|
16
|
+
|
17
|
+
expect { Absolver.set_cause(exc, nil) }.to(
|
18
|
+
change { exc.cause }.from(cause).to(nil)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Exception do
|
4
|
+
describe '#cause=' do
|
5
|
+
let(:exc) { begin; 1 / 0; rescue => e; e; end }
|
6
|
+
let(:cause) { RuntimeError.new('foobar') }
|
7
|
+
|
8
|
+
it 'allows the cause to be set' do
|
9
|
+
expect { exc.cause = cause }.to(
|
10
|
+
change { exc.cause }.from(nil).to(cause)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows the cause to be set to nil' do
|
15
|
+
exc.cause = cause
|
16
|
+
|
17
|
+
expect { exc.cause = nil }.to(
|
18
|
+
change { exc.cause }.from(cause).to(nil)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: absolver
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Dutro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-02-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Allows setting the cause of Ruby exceptions.
|
42
|
+
email:
|
43
|
+
- camertron@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- absolver.gemspec
|
52
|
+
- lib/absolver.rb
|
53
|
+
- lib/absolver/exception.rb
|
54
|
+
- lib/absolver/version.rb
|
55
|
+
- spec/absolver_spec.rb
|
56
|
+
- spec/exception_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
homepage: http://github.com/camertron/absolver
|
59
|
+
licenses: []
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.7.6
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Allows setting the cause of Ruby exceptions.
|
81
|
+
test_files: []
|