to-result 0.1.1 → 0.2.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 +4 -4
- data/Gemfile +2 -4
- data/Gemfile.lock +22 -11
- data/README.md +7 -0
- data/lib/to-result.rb +6 -6
- data/spec/support/fake_object.rb +15 -0
- data/spec/to_result_spec.rb +116 -0
- data/to-result.gemspec +1 -1
- metadata +3 -3
- data/tests/support/fake_logger.rb +0 -9
- data/tests/to_result_test.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9f9dde009ad8e058a1b645888a53f768c8d2571cd91266f77b1017c8aa469ff
|
4
|
+
data.tar.gz: fcbd389f7a3f8d0ddf101cb1064a70a225c039f3cc41c19ca64cac3229469fb9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08e53f93d442d8d5570cb03eac07df8865f6cb4c14bf1daf0eb9f0db064553d879473379cffdc2cd3707100a690d2aebd26340b69d8faea087c9eb17251e5c71'
|
7
|
+
data.tar.gz: 435173009f18e28de610c30424070814b4550e4bb13f5359fda42130eb5fc32887c6004cc6c6aa02b7799b29d74f5b3824b782fdf9c235d90ef5fbd4559dbd07
|
data/Gemfile
CHANGED
@@ -5,10 +5,8 @@ source 'https://rubygems.org'
|
|
5
5
|
# Specify your gem's dependencies in pulsarcli.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
|
-
gem 'dry-monads', '~> 1.
|
8
|
+
gem 'dry-monads', '~> 1.6'
|
9
9
|
|
10
10
|
gem 'byebug', '~> 11.1'
|
11
11
|
|
12
|
-
gem '
|
13
|
-
|
14
|
-
gem 'mocha', '~> 1.15'
|
12
|
+
gem 'rspec'
|
data/Gemfile.lock
CHANGED
@@ -1,33 +1,44 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
to-result (0.
|
4
|
+
to-result (0.2.0)
|
5
5
|
dry-monads (~> 1.5)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
byebug (11.1.3)
|
11
|
-
concurrent-ruby (1.
|
12
|
-
|
11
|
+
concurrent-ruby (1.2.2)
|
12
|
+
diff-lcs (1.5.0)
|
13
|
+
dry-core (1.0.1)
|
13
14
|
concurrent-ruby (~> 1.0)
|
14
15
|
zeitwerk (~> 2.6)
|
15
|
-
dry-monads (1.
|
16
|
+
dry-monads (1.6.0)
|
16
17
|
concurrent-ruby (~> 1.0)
|
17
|
-
dry-core (~> 0
|
18
|
+
dry-core (~> 1.0, < 2)
|
18
19
|
zeitwerk (~> 2.6)
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
rspec (3.12.0)
|
21
|
+
rspec-core (~> 3.12.0)
|
22
|
+
rspec-expectations (~> 3.12.0)
|
23
|
+
rspec-mocks (~> 3.12.0)
|
24
|
+
rspec-core (3.12.2)
|
25
|
+
rspec-support (~> 3.12.0)
|
26
|
+
rspec-expectations (3.12.3)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.12.0)
|
29
|
+
rspec-mocks (3.12.6)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.12.0)
|
32
|
+
rspec-support (3.12.1)
|
33
|
+
zeitwerk (2.6.11)
|
22
34
|
|
23
35
|
PLATFORMS
|
24
36
|
ruby
|
25
37
|
|
26
38
|
DEPENDENCIES
|
27
39
|
byebug (~> 11.1)
|
28
|
-
dry-monads (~> 1.
|
29
|
-
|
30
|
-
mocha (~> 1.15)
|
40
|
+
dry-monads (~> 1.6)
|
41
|
+
rspec
|
31
42
|
to-result!
|
32
43
|
|
33
44
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -180,6 +180,13 @@ e.g. sending the log to Airbrake or whathever service you are using
|
|
180
180
|
- [x] transform/process the catched error => this can be handled with `alt_map` or other methods already available in `dry-monads`
|
181
181
|
- [ ] any type of suggestion is appreciated 😁
|
182
182
|
|
183
|
+
## Relasing a new version
|
184
|
+
|
185
|
+
```
|
186
|
+
gem build to-result
|
187
|
+
gem push to-result-<version>.gem
|
188
|
+
```
|
189
|
+
|
183
190
|
## Authors
|
184
191
|
|
185
192
|
- [@a-chris](https://www.github.com/a-chris)
|
data/lib/to-result.rb
CHANGED
@@ -7,7 +7,7 @@ module ToResultMixin
|
|
7
7
|
attr_accessor :on_error
|
8
8
|
|
9
9
|
def on_error=(value)
|
10
|
-
raise TypeError
|
10
|
+
raise TypeError, 'on_error is expected to be a callable object' unless value.respond_to?(:call)
|
11
11
|
|
12
12
|
@on_error = value
|
13
13
|
end
|
@@ -39,14 +39,14 @@ module ToResultMixin
|
|
39
39
|
# @return [Success]
|
40
40
|
# @return [Failure]
|
41
41
|
#
|
42
|
-
def ToResult(only: [StandardError], **args, &
|
42
|
+
def ToResult(only: [StandardError], **args, &block)
|
43
43
|
# on_error included in args so we can distinguish when it's passed but it's nil
|
44
44
|
# from when it's not passed at all
|
45
45
|
on_error ||= args.key?(:on_error) ? args[:on_error] : @@configuration.on_error
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
block_wrapper =
|
48
|
+
proc do
|
49
|
+
block.call
|
50
50
|
rescue Dry::Monads::Do::Halt => e
|
51
51
|
failure = error = e.result
|
52
52
|
error = error.failure if error.respond_to?(:failure)
|
@@ -57,6 +57,6 @@ module ToResultMixin
|
|
57
57
|
raise e
|
58
58
|
end
|
59
59
|
|
60
|
-
Try.run(only,
|
60
|
+
Try.run(only, block_wrapper).to_result
|
61
61
|
end
|
62
62
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'byebug'
|
2
|
+
|
3
|
+
require './lib/to-result'
|
4
|
+
require './spec/support/fake_object'
|
5
|
+
|
6
|
+
|
7
|
+
RSpec.describe ToResultMixin do
|
8
|
+
include ToResultMixin
|
9
|
+
|
10
|
+
let(:value) { 'hello world!' }
|
11
|
+
|
12
|
+
before do
|
13
|
+
# reset the configuration before each test
|
14
|
+
ToResultMixin.configure { |c| c = {} }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'result handling' do
|
18
|
+
it 'returns a Success with the value of the block' do
|
19
|
+
expect(ToResult { value }).to eq(Success(value))
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns a Success without the Success of the block' do
|
23
|
+
expected = Success(value)
|
24
|
+
expect(ToResult { expected }).to eq(Success(expected))
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a Failure with the exception raised by the block' do
|
28
|
+
expected = StandardError.new(value)
|
29
|
+
expect(ToResult { raise expected }).to eq(Failure(expected))
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns a Failure if the error class is included in `only`' do
|
33
|
+
expected = ArgumentError.new(value)
|
34
|
+
expect(ToResult(only: [ArgumentError]) { raise expected }).to eq(Failure(expected))
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises an error if the error class is not included in `only`' do
|
38
|
+
expected = NameError.new(value)
|
39
|
+
expect { ToResult(only: [ArgumentError]) { raise expected } }.to raise_error(NameError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns Failure if the block raises a Dry::Monads::Do::Halt error' do
|
43
|
+
expected = Dry::Monads::Failure(StandardError.new(value))
|
44
|
+
# it equals to ToResult { yield expected }
|
45
|
+
expect(FakeObject.raise_do_halt_error(expected)).to eq(expected)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'on_error' do
|
50
|
+
it 'passes the unwrapped error to on_error' do
|
51
|
+
local_on_error = proc { |e| FakeObject.log_error(e) }
|
52
|
+
|
53
|
+
expected = StandardError.new(value)
|
54
|
+
failure = Failure(expected)
|
55
|
+
expect(FakeObject).to receive(:log_error).and_return(expected).once
|
56
|
+
# it equals to ToResult { yield expected }
|
57
|
+
expect(FakeObject.raise_do_halt_error(failure, on_error: local_on_error)).to eq(Dry::Monads::Failure.new(expected))
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when gloval callback is not defiend' do
|
61
|
+
it 'uses the local on_error' do
|
62
|
+
local_on_error = proc { |e| FakeObject.log_error(e) }
|
63
|
+
|
64
|
+
expected = StandardError.new(value)
|
65
|
+
expect(FakeObject).to receive(:log_error).and_return(expected).once
|
66
|
+
expect(ToResult(on_error: local_on_error) { raise expected }).to eq(Failure(expected))
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'does not raise error if local on_error is not a proc' do
|
70
|
+
local_on_error = 'not a proc'
|
71
|
+
|
72
|
+
expected = StandardError.new(value)
|
73
|
+
FakeObject.methods(false).each { |m| expect(FakeObject).to receive(m).never }
|
74
|
+
expect(ToResult(on_error: local_on_error) { raise expected }).to eq(Failure(expected))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when global callback is invalid' do
|
79
|
+
it 'raises an error' do
|
80
|
+
expect do
|
81
|
+
ToResultMixin.configure { |c| c.on_error = 'invalid value, should be a proc' }
|
82
|
+
end.to raise_error(TypeError)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when global callback if valid and defined globally' do
|
87
|
+
before do
|
88
|
+
ToResultMixin.configure do |c|
|
89
|
+
c.on_error = proc { |e| FakeObject.log_error(e) }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'calls the global callback' do
|
94
|
+
expected = StandardError.new(value)
|
95
|
+
expect(FakeObject).to receive(:log_error).with(expected).once
|
96
|
+
expect(ToResult { raise expected }).to eq(Failure(expected))
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'uses local on_error over the global one' do
|
100
|
+
local_on_error = Proc.new { |e| FakeObject.log_error_copy(e) }
|
101
|
+
|
102
|
+
expected = StandardError.new(value)
|
103
|
+
expect(FakeObject).to receive(:log_error_copy).with(expected).once
|
104
|
+
expect(ToResult(on_error: local_on_error) { raise expected }).to eq(Failure(expected))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'uses local on_error over the global one even if nil' do
|
108
|
+
local_on_error = nil
|
109
|
+
|
110
|
+
expected = StandardError.new(value)
|
111
|
+
FakeObject.methods(false).each { |m| expect(FakeObject).to receive(m).never }
|
112
|
+
expect(ToResult(on_error: local_on_error) { raise expected }).to eq(Failure(expected))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/to-result.gemspec
CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'to-result'
|
8
|
-
s.version = '0.
|
8
|
+
s.version = '0.2.0'
|
9
9
|
s.summary = 'A wrapper over dry-monads to offer a handy and consistent way to implement the Railway pattern.'
|
10
10
|
s.description = 'A wrapper over dry-monads to offer a handy and consistent way to implement the Railway pattern.'
|
11
11
|
s.authors = ['Christian Toscano']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: to-result
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Toscano
|
@@ -38,8 +38,8 @@ files:
|
|
38
38
|
- README.md
|
39
39
|
- bin/console
|
40
40
|
- lib/to-result.rb
|
41
|
-
-
|
42
|
-
-
|
41
|
+
- spec/support/fake_object.rb
|
42
|
+
- spec/to_result_spec.rb
|
43
43
|
- to-result.gemspec
|
44
44
|
homepage: https://github.com/a-chris/to-result
|
45
45
|
licenses:
|
data/tests/to_result_test.rb
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'mocha/minitest'
|
3
|
-
require 'byebug'
|
4
|
-
|
5
|
-
require './lib/to-result'
|
6
|
-
require './tests/support/fake_logger'
|
7
|
-
|
8
|
-
class ToResultTest < Minitest::Test
|
9
|
-
include ToResultMixin
|
10
|
-
|
11
|
-
def setup
|
12
|
-
super
|
13
|
-
@value = 'hello world!'
|
14
|
-
end
|
15
|
-
|
16
|
-
def teardown
|
17
|
-
super
|
18
|
-
|
19
|
-
# reset the configuration after each test
|
20
|
-
ToResultMixin.configure { |c| c = {} }
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_string
|
24
|
-
assert ToResult { @value } == Success(@value)
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_success
|
28
|
-
expected = Success(@value)
|
29
|
-
assert ToResult { expected } == Success(expected)
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_exception
|
33
|
-
expected = StandardError.new(@value)
|
34
|
-
assert ToResult { raise expected } == Failure(expected)
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_exception_included_in_exceptions_list
|
38
|
-
expected = ArgumentError.new(@value)
|
39
|
-
assert ToResult(only: [ArgumentError]) { raise expected } == Failure(expected)
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_exception_not_included_in_exceptions_list
|
43
|
-
expected = NameError.new(@value)
|
44
|
-
assert_raises(NameError) { ToResult(only: [ArgumentError]) { raise expected } }
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_yield_failure
|
48
|
-
expected = Failure(@value)
|
49
|
-
# this will raise a Dry::Monads::Do::Halt exception
|
50
|
-
assert ToResult { yield expected } == expected
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_yield_failure_exception
|
54
|
-
expected = Failure(StandardError.new(@value))
|
55
|
-
# this will raise a Dry::Monads::Do::Halt exception
|
56
|
-
assert ToResult { yield expected } == expected
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_invalid_global_on_error
|
60
|
-
assert_raises(TypeError) do
|
61
|
-
ToResultMixin.configure { |c| c.on_error = 'invalid value' }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def setup_global_on_error
|
66
|
-
# creating a clean room just for testing purpose
|
67
|
-
clean_room = Class.new(Object)
|
68
|
-
clean_room.new.instance_eval do
|
69
|
-
ToResultMixin.configure do |c|
|
70
|
-
c.on_error = Proc.new { |e| FakeLogger.log_error(e) }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_global_on_error
|
76
|
-
setup_global_on_error
|
77
|
-
|
78
|
-
FakeLogger.expects(:log_error).once
|
79
|
-
|
80
|
-
expected = StandardError.new(@value)
|
81
|
-
|
82
|
-
assert ToResult { raise expected } == Failure(expected)
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_local_on_error_overrides_global
|
86
|
-
setup_global_on_error
|
87
|
-
|
88
|
-
FakeLogger.expects(:log_error).once
|
89
|
-
|
90
|
-
local_on_error = Proc.new { FakeLogger.log_error }
|
91
|
-
|
92
|
-
expected = StandardError.new(@value)
|
93
|
-
assert ToResult(on_error: local_on_error) { raise expected } == Failure(expected)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_local_on_error_overrides_global_nil
|
97
|
-
setup_global_on_error
|
98
|
-
|
99
|
-
FakeLogger.expects(:log_error).never
|
100
|
-
|
101
|
-
local_on_error = nil
|
102
|
-
|
103
|
-
expected = StandardError.new(@value)
|
104
|
-
assert ToResult(on_error: local_on_error) { raise expected } == Failure(expected)
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_local_on_error_without_global
|
108
|
-
local_on_error = Proc.new { |e| FakeLogger.return_error(e) }
|
109
|
-
|
110
|
-
expected = StandardError.new(@value)
|
111
|
-
FakeLogger.expects(:return_error).with(expected).returns(expected).once
|
112
|
-
assert ToResult(on_error: local_on_error) { yield Failure(expected) } == Failure(expected)
|
113
|
-
end
|
114
|
-
end
|