absolver 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -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
@@ -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
@@ -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
@@ -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,7 @@
1
+ require 'absolver'
2
+
3
+ class Exception
4
+ def cause=(new_cause)
5
+ Absolver.set_cause(self, new_cause)
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Absolver
2
+ VERSION = '1.0.0'
3
+ 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
@@ -0,0 +1,8 @@
1
+ $:.push(__dir__)
2
+
3
+ require 'rspec'
4
+ require 'absolver'
5
+ require 'absolver/exception'
6
+
7
+ RSpec.configure do |config|
8
+ end
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: []