bcdd-result 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +14 -7
- data/CHANGELOG.md +21 -2
- data/README.md +166 -9
- data/lib/bcdd/result/error.rb +1 -1
- data/lib/bcdd/result/expectations/mixin.rb +37 -0
- data/lib/bcdd/result/expectations.rb +5 -17
- data/lib/bcdd/result/mixin.rb +31 -4
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +6 -3
- data/sig/bcdd/result.rbs +34 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d43af37c2ffd8d2764fc62039ac1d3e4398b2872fa25bc80192a9aca1b08dfb5
|
4
|
+
data.tar.gz: 8aaab364445f279d207390479bce6680c4ed4b7fe4b2fc026e203ddece47a398
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dbac4fdded1e36d6f2af6e5c7e0d0bebfe44b489410a35445935c8da656fe244fca7a6e769a5b73d6070929e790be420887b2576cb9b523a798fe3ff759e564
|
7
|
+
data.tar.gz: 12055de39a9a3a93f69670da7b3a93a0e3749568590be14d02ce750cb5b5e5b00c7b56da422941bdea8842b073573e589d2a11681496f18f7160ddeaf3ceb7bb
|
data/.rubocop.yml
CHANGED
@@ -18,10 +18,6 @@ Layout/ExtraSpacing:
|
|
18
18
|
Style/ClassAndModuleChildren:
|
19
19
|
Enabled: false
|
20
20
|
|
21
|
-
Style/MapToSet:
|
22
|
-
Exclude:
|
23
|
-
- lib/bcdd/result/expectations/contract/for_types.rb
|
24
|
-
|
25
21
|
Style/CaseEquality:
|
26
22
|
Exclude:
|
27
23
|
- lib/bcdd/result/expectations/contract/for_types_and_values.rb
|
@@ -29,13 +25,21 @@ Style/CaseEquality:
|
|
29
25
|
Style/Lambda:
|
30
26
|
EnforcedStyle: literal
|
31
27
|
|
28
|
+
Style/MapToSet:
|
29
|
+
Exclude:
|
30
|
+
- lib/bcdd/result/expectations/contract/for_types.rb
|
31
|
+
|
32
|
+
Style/MixinGrouping:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Style/AccessModifierDeclarations:
|
36
|
+
Enabled: false
|
37
|
+
|
32
38
|
Naming/MethodName:
|
33
39
|
Exclude:
|
34
40
|
- lib/bcdd/result/mixin.rb
|
35
41
|
- lib/bcdd/result/expectations.rb
|
36
|
-
|
37
|
-
Minitest/MultipleAssertions:
|
38
|
-
Enabled: false
|
42
|
+
- lib/bcdd/result/expectations/mixin.rb
|
39
43
|
|
40
44
|
Metrics/BlockLength:
|
41
45
|
Exclude:
|
@@ -45,3 +49,6 @@ Metrics/BlockLength:
|
|
45
49
|
Metrics/ClassLength:
|
46
50
|
Exclude:
|
47
51
|
- test/**/*.rb
|
52
|
+
|
53
|
+
Minitest/MultipleAssertions:
|
54
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,27 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.6.0] - 2023-10-11
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Add `BCDD::Result.mixin` to be included or extended in any object. It will add `Success()` and `Failure()` to the target object (the object who receives the include/extend).
|
8
|
+
|
9
|
+
- Add `BCDD::Result.mixin(with: :Continue)`. This addon will add a `Continue(value)` method to the target object to produce a `Success(:continued, value)` result.
|
10
|
+
|
11
|
+
- Add `BCDD::Result::Expectations.mixin(with: :Continue)`, it is similar to `BCDD::Result.mixin(with: :Continue)`, the key difference is that the `Continue(value)` will be ignored by the expectations. This is extremely useful when you want to use `Continue(value)` to chain operations, but you don't want to declare N success types in the expectations.
|
12
|
+
|
13
|
+
- Increase the arity of `BCDD::Result#and_then`. Now, it can receive a second argument (a value to be injected and shared with the subject's method).
|
14
|
+
|
15
|
+
- Increase the arity (maximum of 2) for the methods called through `BCDD::Result#and_then`. The second argument is the value injected by `BCDD::Result#and_then`.
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- **(BREAKING)** Make `BCDD::Result::Mixin` be a private constant. The `BCDD::Result.mixin` method is the new way to use it.
|
20
|
+
|
3
21
|
## [0.5.0] - 2023-10-09
|
4
22
|
|
23
|
+
### Added
|
24
|
+
|
5
25
|
- Add `BCDD::Result::Expectations` to define contracts for your results. There are two ways to use it: the standalone (`BCDD::Result::Expectations.new`) and the mixin (`BCDD::Result::Expectations.mixin`) mode.
|
6
26
|
|
7
27
|
The main difference is that the mixin mode will use the target object (who receives the include/extend) as the result's subject (like the `BCDD::Result::Mixin` does), while the standalone mode won't.
|
@@ -152,8 +172,7 @@ end
|
|
152
172
|
|
153
173
|
```ruby
|
154
174
|
module Divide
|
155
|
-
extend BCDD::Resultable
|
156
|
-
extend self
|
175
|
+
extend self, BCDD::Resultable
|
157
176
|
|
158
177
|
def call(arg1, arg2)
|
159
178
|
validate_numbers(arg1, arg2)
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<p align="center"><i>Empower Ruby apps with a pragmatic use of Railway Oriented Programming.</i></p>
|
4
4
|
<p align="center">
|
5
5
|
<img src="https://img.shields.io/badge/ruby->%3D%202.7.0-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
6
|
-
<img src="https://badge.fury.io/rb/bcdd-result.svg" alt="bcdd-result gem version" height="18">
|
6
|
+
<a href="https://rubygems.org/gems/bcdd-result"><img src="https://badge.fury.io/rb/bcdd-result.svg" alt="bcdd-result gem version" height="18"></a>
|
7
7
|
</p>
|
8
8
|
</p>
|
9
9
|
|
@@ -37,10 +37,12 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
37
37
|
- [`result.data`](#resultdata)
|
38
38
|
- [Railway Oriented Programming](#railway-oriented-programming)
|
39
39
|
- [`result.and_then`](#resultand_then)
|
40
|
-
- [`BCDD::Result
|
40
|
+
- [`BCDD::Result.mixin`](#bcddresultmixin)
|
41
41
|
- [Class example (Instance Methods)](#class-example-instance-methods)
|
42
42
|
- [Module example (Singleton Methods)](#module-example-singleton-methods)
|
43
|
-
- [
|
43
|
+
- [Important Requirement](#important-requirement)
|
44
|
+
- [Dependency Injection](#dependency-injection)
|
45
|
+
- [Addons](#addons)
|
44
46
|
- [Pattern Matching](#pattern-matching)
|
45
47
|
- [`Array`/`Find` patterns](#arrayfind-patterns)
|
46
48
|
- [`Hash` patterns](#hash-patterns)
|
@@ -58,6 +60,7 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
58
60
|
- [Value checking - Result Creation](#value-checking---result-creation)
|
59
61
|
- [Success()](#success)
|
60
62
|
- [Failure()](#failure)
|
63
|
+
- [`BCDD::Result::Expectations.mixin` Addons](#bcddresultexpectationsmixin-addons)
|
61
64
|
- [About](#about)
|
62
65
|
- [Development](#development)
|
63
66
|
- [Contributing](#contributing)
|
@@ -521,9 +524,9 @@ Divide.call(2, 2)
|
|
521
524
|
|
522
525
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
523
526
|
|
524
|
-
#### `BCDD::Result
|
527
|
+
#### `BCDD::Result.mixin`
|
525
528
|
|
526
|
-
|
529
|
+
This method produces a module that can be included/extended by any object. It adds two methods to the target object: `Success()` and `Failure()`. The main difference between these methods and `BCDD::Result::Success()`/`BCDD::Result::Failure()` is that the first ones will use the target object (who received the include/extend) as the result's subject.
|
527
530
|
|
528
531
|
And because of this, you can use the `#and_then` method to call methods from the result's subject.
|
529
532
|
|
@@ -531,7 +534,7 @@ And because of this, you can use the `#and_then` method to call methods from the
|
|
531
534
|
|
532
535
|
```ruby
|
533
536
|
class Divide
|
534
|
-
include BCDD::Result
|
537
|
+
include BCDD::Result.mixin
|
535
538
|
|
536
539
|
attr_reader :arg1, :arg2
|
537
540
|
|
@@ -579,8 +582,7 @@ Divide.new(4, '2').call #<BCDD::Result::Failure type=:invalid_arg value="arg2 mu
|
|
579
582
|
|
580
583
|
```ruby
|
581
584
|
module Divide
|
582
|
-
extend BCDD::Result
|
583
|
-
extend self
|
585
|
+
extend self, BCDD::Result.mixin
|
584
586
|
|
585
587
|
def call(arg1, arg2)
|
586
588
|
validate_numbers(arg1, arg2)
|
@@ -615,7 +617,9 @@ Divide.call('4', 2) #<BCDD::Result::Failure type=:invalid_arg value="arg1 must b
|
|
615
617
|
Divide.call(4, '2') #<BCDD::Result::Failure type=:invalid_arg value="arg2 must be numeric">
|
616
618
|
```
|
617
619
|
|
618
|
-
|
620
|
+
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
621
|
+
|
622
|
+
##### Important Requirement
|
619
623
|
|
620
624
|
The unique condition for using the `#and_then` to call methods is that they must use the `Success()` and `Failure()` to produce their results.
|
621
625
|
|
@@ -625,6 +629,104 @@ If you use `BCDD::Result::Subject()`/`BCDD::Result::Failure()`, or use result fr
|
|
625
629
|
|
626
630
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
627
631
|
|
632
|
+
##### Dependency Injection
|
633
|
+
|
634
|
+
The `BCDD::Result#and_then` accepts a second argument that will be used to share a value with the subject's method. To receive this argument, the subject's method must have an arity of two, where the first argument will be the result value and the second will be the shared value.
|
635
|
+
|
636
|
+
```ruby
|
637
|
+
require 'logger'
|
638
|
+
|
639
|
+
module Divide
|
640
|
+
extend self, BCDD::Result.mixin
|
641
|
+
|
642
|
+
def call(arg1, arg2, logger: ::Logger.new(STDOUT))
|
643
|
+
validate_numbers(arg1, arg2)
|
644
|
+
.and_then(:validate_non_zero, logger)
|
645
|
+
.and_then(:divide, logger)
|
646
|
+
end
|
647
|
+
|
648
|
+
private
|
649
|
+
|
650
|
+
def validate_numbers(arg1, arg2)
|
651
|
+
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
|
652
|
+
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')
|
653
|
+
|
654
|
+
Success(:ok, [arg1, arg2])
|
655
|
+
end
|
656
|
+
|
657
|
+
def validate_non_zero(numbers, logger)
|
658
|
+
if numbers.last.zero?
|
659
|
+
logger.error('arg2 must not be zero')
|
660
|
+
|
661
|
+
Failure(:division_by_zero, 'arg2 must not be zero')
|
662
|
+
else
|
663
|
+
logger.info('The numbers are valid')
|
664
|
+
|
665
|
+
Success(:ok, numbers)
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
def divide((number1, number2), logger)
|
670
|
+
division = number1 / number2
|
671
|
+
|
672
|
+
logger.info("The division result is #{division}")
|
673
|
+
|
674
|
+
Success(:division_completed, division)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
Divide.call(4, 2)
|
679
|
+
# I, [2023-10-11T00:08:05.546237 #18139] INFO -- : The numbers are valid
|
680
|
+
# I, [2023-10-11T00:08:05.546337 #18139] INFO -- : The division result is 2
|
681
|
+
#=> #<BCDD::Result::Success type=:division_completed value=2>
|
682
|
+
|
683
|
+
Divide.call(4, 2, logger: Logger.new(IO::NULL))
|
684
|
+
#=> #<BCDD::Result::Success type=:division_completed value=2>
|
685
|
+
```
|
686
|
+
|
687
|
+
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
688
|
+
|
689
|
+
##### Addons
|
690
|
+
|
691
|
+
The `BCDD::Result.mixin` also accepts the `with:` argument. It is a hash that will be used to define the methods that will be added to the target object.
|
692
|
+
|
693
|
+
**Continue**
|
694
|
+
|
695
|
+
This addon will create the `Continue(value)` method, which will know how to produce a `Success(:continued, value)`. It is useful when you want to perform a sequence of operations but want to avoid returning a specific result for each step.
|
696
|
+
|
697
|
+
```ruby
|
698
|
+
module Divide
|
699
|
+
extend self, BCDD::Result.mixin(with: :Continue)
|
700
|
+
|
701
|
+
def call(arg1, arg2)
|
702
|
+
validate_numbers(arg1, arg2)
|
703
|
+
.and_then(:validate_non_zero)
|
704
|
+
.and_then(:divide)
|
705
|
+
end
|
706
|
+
|
707
|
+
private
|
708
|
+
|
709
|
+
def validate_numbers(arg1, arg2)
|
710
|
+
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
|
711
|
+
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')
|
712
|
+
|
713
|
+
Continue([arg1, arg2])
|
714
|
+
end
|
715
|
+
|
716
|
+
def validate_non_zero(numbers)
|
717
|
+
return Continue(numbers) unless numbers.last.zero?
|
718
|
+
|
719
|
+
Failure(:division_by_zero, 'arg2 must not be zero')
|
720
|
+
end
|
721
|
+
|
722
|
+
def divide((number1, number2))
|
723
|
+
Success(:division_completed, number1 / number2)
|
724
|
+
end
|
725
|
+
end
|
726
|
+
```
|
727
|
+
|
728
|
+
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
729
|
+
|
628
730
|
### Pattern Matching
|
629
731
|
|
630
732
|
The `BCDD::Result` also provides support to pattern matching.
|
@@ -1071,6 +1173,61 @@ Divide::Expected::Failure(:division_by_zero, msg: 'arg2 must not be zero')
|
|
1071
1173
|
|
1072
1174
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
1073
1175
|
|
1176
|
+
#### `BCDD::Result::Expectations.mixin` Addons
|
1177
|
+
|
1178
|
+
The `BCDD::Result::Expectations.mixin` also accepts the `with:` argument. It is a hash that will be used to define the methods that will be added to the target object.
|
1179
|
+
|
1180
|
+
**Continue**
|
1181
|
+
|
1182
|
+
It is similar to `BCDD::Result.mixin(with: :Continue)`, the key difference is that the `Continue(value)` will be ignored by the expectations. This is extremely useful when you want to use `Continue(value)` to chain operations, but you don't want to declare N success types in the expectations.
|
1183
|
+
|
1184
|
+
```ruby
|
1185
|
+
class Divide
|
1186
|
+
include BCDD::Result::Expectations.mixin(
|
1187
|
+
with: :Continue,
|
1188
|
+
success: :division_completed,
|
1189
|
+
failure: %i[invalid_arg division_by_zero]
|
1190
|
+
)
|
1191
|
+
|
1192
|
+
def call(arg1, arg2)
|
1193
|
+
validate_numbers(arg1, arg2)
|
1194
|
+
.and_then(:validate_non_zero)
|
1195
|
+
.and_then(:divide)
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
private
|
1199
|
+
|
1200
|
+
def validate_numbers(arg1, arg2)
|
1201
|
+
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
|
1202
|
+
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')
|
1203
|
+
|
1204
|
+
Continue([arg1, arg2])
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
def validate_non_zero(numbers)
|
1208
|
+
return Continue(numbers) unless numbers.last.zero?
|
1209
|
+
|
1210
|
+
Failure(:division_by_zero, 'arg2 must not be zero')
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
def divide((number1, number2))
|
1214
|
+
Success(:division_completed, number1 / number2)
|
1215
|
+
end
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
result = Divide.new.call(4,2)
|
1219
|
+
# => #<BCDD::Result::Success type=:division_completed value=2>
|
1220
|
+
|
1221
|
+
# The example below shows an error because the :ok type is not allowed.
|
1222
|
+
# But look at the allowed types have only one type (:division_completed).
|
1223
|
+
# This is because the :continued type is ignored by the expectations.
|
1224
|
+
#
|
1225
|
+
result.success?(:ok)
|
1226
|
+
# type :ok is not allowed. Allowed types: :division_completed (BCDD::Result::Expectations::Error::UnexpectedType)
|
1227
|
+
```
|
1228
|
+
|
1229
|
+
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
1230
|
+
|
1074
1231
|
## About
|
1075
1232
|
|
1076
1233
|
[Rodrigo Serradura](https://github.com/serradura) created this project. He is the B/CDD process/method creator and has already made similar gems like the [u-case](https://github.com/serradura/u-case) and [kind](https://github.com/serradura/kind/blob/main/lib/kind/result.rb). This gem is a general-purpose abstraction/monad, but it also contains key features that serve as facilitators for adopting B/CDD in the code.
|
data/lib/bcdd/result/error.rb
CHANGED
@@ -38,7 +38,7 @@ class BCDD::Result::Error < StandardError
|
|
38
38
|
|
39
39
|
class WrongSubjectMethodArity < self
|
40
40
|
def self.build(subject:, method:)
|
41
|
-
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0 or
|
41
|
+
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0, 1 or 2.")
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
module Mixin
|
5
|
+
METHODS = <<~RUBY
|
6
|
+
def Success(...)
|
7
|
+
__expected::Success(...)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(...)
|
11
|
+
__expected::Failure(...)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def __expected
|
17
|
+
@__expected ||= Expected.with(subject: self)
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
|
21
|
+
module Addons
|
22
|
+
module Continuable
|
23
|
+
private def Continue(value)
|
24
|
+
::BCDD::Result::Success.new(type: :continued, value: value, subject: self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
OPTIONS = { Continue: Continuable }.freeze
|
29
|
+
|
30
|
+
def self.options(names)
|
31
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private_constant :Mixin
|
37
|
+
end
|
@@ -1,30 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class BCDD::Result::Expectations
|
4
|
+
require_relative 'expectations/mixin'
|
4
5
|
require_relative 'expectations/error'
|
5
6
|
require_relative 'expectations/contract'
|
6
7
|
require_relative 'expectations/type_checker'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
_expected_result::Success(...)
|
11
|
-
end
|
9
|
+
def self.mixin(success: nil, failure: nil, with: nil)
|
10
|
+
addons = Mixin::Addons.options(with)
|
12
11
|
|
13
|
-
def Failure(...)
|
14
|
-
_expected_result::Failure(...)
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def _expected_result
|
20
|
-
@_expected_result ||= Expected.with(subject: self)
|
21
|
-
end
|
22
|
-
RUBY
|
23
|
-
|
24
|
-
def self.mixin(success: nil, failure: nil)
|
25
12
|
mod = Module.new
|
26
13
|
mod.const_set(:Expected, new(success: success, failure: failure).freeze)
|
27
|
-
mod.module_eval(
|
14
|
+
mod.module_eval(Mixin::METHODS)
|
15
|
+
mod.send(:include, *addons) unless addons.empty?
|
28
16
|
mod
|
29
17
|
end
|
30
18
|
|
data/lib/bcdd/result/mixin.rb
CHANGED
@@ -2,12 +2,39 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
module Mixin
|
5
|
-
|
6
|
-
Success
|
5
|
+
module Methods
|
6
|
+
def Success(type, value = nil)
|
7
|
+
Success.new(type: type, value: value, subject: self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(type, value = nil)
|
11
|
+
Failure.new(type: type, value: value, subject: self)
|
12
|
+
end
|
7
13
|
end
|
8
14
|
|
9
|
-
|
10
|
-
|
15
|
+
module Addons
|
16
|
+
module Continuable
|
17
|
+
private def Continue(value)
|
18
|
+
Success(:continued, value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
OPTIONS = { Continue: Continuable }.freeze
|
23
|
+
|
24
|
+
def self.options(names)
|
25
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
26
|
+
end
|
11
27
|
end
|
12
28
|
end
|
29
|
+
|
30
|
+
def self.mixin(with: nil)
|
31
|
+
addons = Mixin::Addons.options(with)
|
32
|
+
|
33
|
+
mod = Module.new
|
34
|
+
mod.send(:include, Mixin::Methods)
|
35
|
+
mod.send(:include, *addons) unless addons.empty?
|
36
|
+
mod
|
37
|
+
end
|
38
|
+
|
39
|
+
private_constant :Mixin
|
13
40
|
end
|
data/lib/bcdd/result/version.rb
CHANGED
data/lib/bcdd/result.rb
CHANGED
@@ -66,10 +66,12 @@ class BCDD::Result
|
|
66
66
|
tap { yield(value, type) if unknown }
|
67
67
|
end
|
68
68
|
|
69
|
-
def and_then(method_name = nil)
|
69
|
+
def and_then(method_name = nil, context = nil)
|
70
70
|
return self if failure?
|
71
71
|
|
72
|
-
|
72
|
+
method_name && block_given? and raise ArgumentError, 'method_name and block are mutually exclusive'
|
73
|
+
|
74
|
+
return call_subject_method(method_name, context) if method_name
|
73
75
|
|
74
76
|
result = yield(value)
|
75
77
|
|
@@ -119,13 +121,14 @@ class BCDD::Result
|
|
119
121
|
block.call(value, type)
|
120
122
|
end
|
121
123
|
|
122
|
-
def call_subject_method(method_name)
|
124
|
+
def call_subject_method(method_name, context)
|
123
125
|
method = subject.method(method_name)
|
124
126
|
|
125
127
|
result =
|
126
128
|
case method.arity
|
127
129
|
when 0 then subject.send(method_name)
|
128
130
|
when 1 then subject.send(method_name, value)
|
131
|
+
when 2 then subject.send(method_name, value, context)
|
129
132
|
else raise Error::WrongSubjectMethodArity.build(subject: subject, method: method)
|
130
133
|
end
|
131
134
|
|
data/sig/bcdd/result.rbs
CHANGED
@@ -31,7 +31,7 @@ class BCDD::Result
|
|
31
31
|
def on_failure: (*Symbol) { (untyped, Symbol) -> void } -> BCDD::Result
|
32
32
|
def on_unknown: () { (untyped, Symbol) -> void } -> BCDD::Result
|
33
33
|
|
34
|
-
def and_then: (?Symbol method_name) { (untyped) -> untyped } -> BCDD::Result
|
34
|
+
def and_then: (?Symbol method_name, ?untyped context) ?{ (untyped) -> untyped } -> BCDD::Result
|
35
35
|
|
36
36
|
def handle: () { (BCDD::Result::Handler) -> void } -> untyped
|
37
37
|
|
@@ -49,7 +49,7 @@ class BCDD::Result
|
|
49
49
|
|
50
50
|
def name: -> Symbol
|
51
51
|
def known: (Proc) -> untyped
|
52
|
-
def call_subject_method: (Symbol) -> BCDD::Result
|
52
|
+
def call_subject_method: (Symbol, untyped) -> BCDD::Result
|
53
53
|
def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result
|
54
54
|
end
|
55
55
|
|
@@ -69,10 +69,26 @@ end
|
|
69
69
|
|
70
70
|
class BCDD::Result
|
71
71
|
module Mixin
|
72
|
-
|
72
|
+
module Methods
|
73
|
+
def Success: (Symbol type, ?untyped value) -> BCDD::Result::Success
|
73
74
|
|
74
|
-
|
75
|
+
def Failure: (Symbol type, ?untyped value) -> BCDD::Result::Failure
|
76
|
+
end
|
77
|
+
|
78
|
+
module Addons
|
79
|
+
module Continuable
|
80
|
+
include BCDD::Result::Mixin::Methods
|
81
|
+
|
82
|
+
private def Continue: (untyped) -> BCDD::Result::Success
|
83
|
+
end
|
84
|
+
|
85
|
+
OPTIONS: Hash[Symbol, Module]
|
86
|
+
|
87
|
+
def self.options: (Array[Symbol]) -> Array[Module]
|
88
|
+
end
|
75
89
|
end
|
90
|
+
|
91
|
+
def self.mixin: (?with: Array[Symbol]) -> Module
|
76
92
|
end
|
77
93
|
|
78
94
|
class BCDD::Result
|
@@ -201,6 +217,20 @@ class BCDD::Result::Expectations
|
|
201
217
|
attr_reader contract: BCDD::Result::Expectations::Contract::Evaluator
|
202
218
|
end
|
203
219
|
|
220
|
+
module BCDD::Result::Expectations::Mixin
|
221
|
+
METHODS: String
|
222
|
+
|
223
|
+
module Addons
|
224
|
+
module Continuable
|
225
|
+
private def Continue: (untyped) -> BCDD::Result::Success
|
226
|
+
end
|
227
|
+
|
228
|
+
OPTIONS: Hash[Symbol, Module]
|
229
|
+
|
230
|
+
def self.options: (Array[Symbol]) -> Array[Module]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
204
234
|
module BCDD::Result::Expectations::Contract
|
205
235
|
NONE: BCDD::Result::Expectations::Contract::Evaluator
|
206
236
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bcdd-result
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
Empower Ruby apps with a pragmatic use of Railway Oriented Programming.
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- lib/bcdd/result/expectations/contract/for_types_and_values.rb
|
40
40
|
- lib/bcdd/result/expectations/contract/interface.rb
|
41
41
|
- lib/bcdd/result/expectations/error.rb
|
42
|
+
- lib/bcdd/result/expectations/mixin.rb
|
42
43
|
- lib/bcdd/result/expectations/type_checker.rb
|
43
44
|
- lib/bcdd/result/failure.rb
|
44
45
|
- lib/bcdd/result/handler.rb
|