to-result 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc48c861de210a05cba164c61710457447f04b60b492ef15791ab7e5c28a3375
4
- data.tar.gz: fb5802866e75958e710ec9a0be23584f8f737101ef8afd18c5b212a775539c1c
3
+ metadata.gz: d9f9dde009ad8e058a1b645888a53f768c8d2571cd91266f77b1017c8aa469ff
4
+ data.tar.gz: fcbd389f7a3f8d0ddf101cb1064a70a225c039f3cc41c19ca64cac3229469fb9
5
5
  SHA512:
6
- metadata.gz: 60728e022ce553988082effc1ab86a3260cf399a464bddea06d936e6428bf54f0604a8b86638ee7932526a20d72b3c80bcc491f6d816d6d17bdd93326c11b2ce
7
- data.tar.gz: 959d7af9b3eb1367269c6650ca9c9babedd8c3cfd6e36403d3d4f01b750219dc7781cec78e4bc2a4972ce34e230d157dbd17a8bee70b7c9cc24c407fb71f5bc3
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.5'
8
+ gem 'dry-monads', '~> 1.6'
9
9
 
10
10
  gem 'byebug', '~> 11.1'
11
11
 
12
- gem 'minitest', '~> 5.16'
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.1.1)
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.1.10)
12
- dry-core (0.9.1)
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.5.0)
16
+ dry-monads (1.6.0)
16
17
  concurrent-ruby (~> 1.0)
17
- dry-core (~> 0.9, >= 0.9)
18
+ dry-core (~> 1.0, < 2)
18
19
  zeitwerk (~> 2.6)
19
- minitest (5.16.3)
20
- mocha (1.15.0)
21
- zeitwerk (2.6.1)
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.5)
29
- minitest (~> 5.16)
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.new('on_error is expected to be a callable object') unless value.respond_to?(:call)
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, &f)
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
- f_wrapper =
48
- Proc.new do
49
- f.call
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, f_wrapper).to_result
60
+ Try.run(only, block_wrapper).to_result
61
61
  end
62
62
  end
@@ -0,0 +1,15 @@
1
+ class FakeObject
2
+ extend ToResultMixin
3
+
4
+ def self.log_error(e)
5
+ e
6
+ end
7
+
8
+ def self.log_error_copy(e)
9
+ e
10
+ end
11
+
12
+ def self.raise_do_halt_error(failure, on_error: nil)
13
+ ToResult(on_error: on_error) { yield failure }
14
+ end
15
+ 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.1.1'
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.1.1
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
- - tests/support/fake_logger.rb
42
- - tests/to_result_test.rb
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:
@@ -1,9 +0,0 @@
1
- class FakeLogger
2
- def self.log_error(e)
3
- e
4
- end
5
-
6
- def self.return_error(e)
7
- e
8
- end
9
- end
@@ -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