bcdd-result 0.2.0 → 0.3.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/.rubocop_todo.yml +4 -2
- data/CHANGELOG.md +6 -0
- data/README.md +60 -4
- data/lib/bcdd/result/handler.rb +48 -0
- data/lib/bcdd/result/type.rb +17 -0
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +19 -13
- data/sig/bcdd/result.rbs +40 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96c58d6a9132fbf42fc8f3c1d9ba683f0b6297e23b1f0536fc4bcb7efb5084df
|
4
|
+
data.tar.gz: fcef45f3c5ddacc20ff5e9533012c7fbe5817878cef1ff528dabd8920e1cbccd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4cf048907571205c6cd0b90ca4b95c2480c34de79d082132e4f1cab1e809f4c6eec538d9d38b036ad313d9653420625b68a502272e73371b99b157f43315123
|
7
|
+
data.tar.gz: 4662aaeb33a7eb770ab51529cc1f2c4e9d86844dec70dfcdc4f37674aab33d010d6cbe7932fc635f09979d47b4b631748a3d4791021e99108a011a93469a2d73
|
data/.rubocop_todo.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2023-09-
|
3
|
+
# on 2023-09-27 00:47:03 UTC using RuboCop version 1.56.3.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 13
|
10
10
|
# Configuration parameters: AllowedConstants.
|
11
11
|
Style/Documentation:
|
12
12
|
Exclude:
|
@@ -15,5 +15,7 @@ Style/Documentation:
|
|
15
15
|
- 'lib/bcdd/result.rb'
|
16
16
|
- 'lib/bcdd/result/error.rb'
|
17
17
|
- 'lib/bcdd/result/failure.rb'
|
18
|
+
- 'lib/bcdd/result/handler.rb'
|
18
19
|
- 'lib/bcdd/result/success.rb'
|
20
|
+
- 'lib/bcdd/result/type.rb'
|
19
21
|
- 'lib/bcdd/resultable.rb'
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2023-09-26
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Add `BCDD::Result#handle`. This method allows defining blocks for each hook (type, failure, success), but instead of returning the result itself, it will return the output of the first match/block execution.
|
8
|
+
|
3
9
|
## [0.2.0] - 2023-09-26
|
4
10
|
|
5
11
|
### Added
|
data/README.md
CHANGED
@@ -14,6 +14,7 @@ Furthermore, this abstraction exposes several features that will be useful to ma
|
|
14
14
|
|
15
15
|
Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/) pattern (superpower) in your code.
|
16
16
|
|
17
|
+
- [Ruby Version](#ruby-version)
|
17
18
|
- [Installation](#installation)
|
18
19
|
- [Usage](#usage)
|
19
20
|
- [Reference](#reference)
|
@@ -24,6 +25,7 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
24
25
|
- [`result.on_type`](#resulton_type)
|
25
26
|
- [`result.on_success`](#resulton_success)
|
26
27
|
- [`result.on_failure`](#resulton_failure)
|
28
|
+
- [`result.handle`](#resulthandle)
|
27
29
|
- [Result Value](#result-value)
|
28
30
|
- [`result.value_or`](#resultvalue_or)
|
29
31
|
- [`result.data_or`](#resultdata_or)
|
@@ -39,18 +41,26 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
39
41
|
- [License](#license)
|
40
42
|
- [Code of Conduct](#code-of-conduct)
|
41
43
|
|
44
|
+
## Ruby Version
|
45
|
+
|
46
|
+
`>= 2.7.0`
|
47
|
+
|
42
48
|
## Installation
|
43
49
|
|
44
|
-
|
50
|
+
Add this line to your application's Gemfile:
|
45
51
|
|
46
|
-
|
52
|
+
```ruby
|
53
|
+
gem 'bcdd-result', require: 'bcdd/result'
|
54
|
+
```
|
55
|
+
|
56
|
+
And then execute:
|
57
|
+
|
58
|
+
$ bundle install
|
47
59
|
|
48
60
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
49
61
|
|
50
62
|
$ gem install bcdd-result
|
51
63
|
|
52
|
-
> **NOTE:** This gem is compatible with Ruby >= 2.7.0
|
53
|
-
|
54
64
|
<p align="right">(<a href="#-bcddresult">⬆️ back to top</a>)</p>
|
55
65
|
|
56
66
|
## Usage
|
@@ -263,6 +273,52 @@ divide(4, 0).on_failure(:invalid_arg) { |error| puts error }
|
|
263
273
|
|
264
274
|
<p align="right">(<a href="#-bcddresult">⬆️ back to top</a>)</p>
|
265
275
|
|
276
|
+
#### `result.handle`
|
277
|
+
|
278
|
+
This method will allow you to define blocks for each hook (type, failure, success), but instead of returning itself, it will return the output of the first match/block execution.
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
divide(4, 2).handle do |result|
|
282
|
+
result.success { |number| number }
|
283
|
+
result.failure(:invalid_arg) { |err| puts err }
|
284
|
+
result.type(:division_by_zero) { raise ZeroDivisionError }
|
285
|
+
end
|
286
|
+
|
287
|
+
#or
|
288
|
+
|
289
|
+
divide(4, 2).handle do |on|
|
290
|
+
on.success { |number| number }
|
291
|
+
on.failure { |err| puts err }
|
292
|
+
end
|
293
|
+
|
294
|
+
#or
|
295
|
+
|
296
|
+
divide(4, 2).handle do |on|
|
297
|
+
on.type(:invalid_arg) { |err| puts err }
|
298
|
+
on.type(:division_by_zero) { raise ZeroDivisionError }
|
299
|
+
on.type(:division_completed) { |number| number }
|
300
|
+
end
|
301
|
+
|
302
|
+
# or
|
303
|
+
|
304
|
+
divide(4, 2).handle do |on|
|
305
|
+
on[:invalid_arg] { |err| puts err }
|
306
|
+
on[:division_by_zero] { raise ZeroDivisionError }
|
307
|
+
on[:division_completed] { |number| number }
|
308
|
+
end
|
309
|
+
|
310
|
+
# The [] syntax 👆 is an alias of #type.
|
311
|
+
```
|
312
|
+
|
313
|
+
**Notes:**
|
314
|
+
* You can define multiple types to be handled by the same hook/block
|
315
|
+
* If the type is missing, it will perform the block for any success or failure handler.
|
316
|
+
* The `#type` and `#[]` handlers will require at least one type/argument.
|
317
|
+
|
318
|
+
*PS: The `divide()` implementation is [here](#result-hooks).*
|
319
|
+
|
320
|
+
<p align="right">(<a href="#-bcddresult">⬆️ back to top</a>)</p>
|
321
|
+
|
266
322
|
### Result Value
|
267
323
|
|
268
324
|
The most simple way to get the result value is by calling `BCDD::Result#value` or `BCDD::Result#data`.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class Handler
|
5
|
+
UNDEFINED = ::Object.new
|
6
|
+
|
7
|
+
def initialize(result)
|
8
|
+
@outcome = UNDEFINED
|
9
|
+
|
10
|
+
@_type = result._type
|
11
|
+
@result = result
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](*types, &block)
|
15
|
+
raise Error::MissingTypeArgument if types.empty?
|
16
|
+
|
17
|
+
self.outcome = block if _type.in?(types, allow_empty: false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure(*types, &block)
|
21
|
+
self.outcome = block if result.failure? && _type.in?(types, allow_empty: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def success(*types, &block)
|
25
|
+
self.outcome = block if result.success? && _type.in?(types, allow_empty: true)
|
26
|
+
end
|
27
|
+
|
28
|
+
alias type []
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :_type, :result
|
33
|
+
|
34
|
+
def outcome?
|
35
|
+
@outcome != UNDEFINED
|
36
|
+
end
|
37
|
+
|
38
|
+
def outcome
|
39
|
+
@outcome if outcome?
|
40
|
+
end
|
41
|
+
|
42
|
+
def outcome=(block)
|
43
|
+
@outcome = block.call(result.value, result.type) unless outcome?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private_constant :Handler
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class Type
|
5
|
+
attr_reader :to_sym
|
6
|
+
|
7
|
+
def initialize(type)
|
8
|
+
@to_sym = type.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def in?(types, allow_empty: false)
|
12
|
+
(allow_empty && types.empty?) || types.any?(to_sym)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private_constant :Type
|
17
|
+
end
|
data/lib/bcdd/result/version.rb
CHANGED
data/lib/bcdd/result.rb
CHANGED
@@ -2,22 +2,28 @@
|
|
2
2
|
|
3
3
|
require_relative 'result/version'
|
4
4
|
require_relative 'result/error'
|
5
|
+
require_relative 'result/type'
|
6
|
+
require_relative 'result/handler'
|
5
7
|
require_relative 'result/failure'
|
6
8
|
require_relative 'result/success'
|
7
9
|
|
8
10
|
require_relative 'resultable'
|
9
11
|
|
10
12
|
class BCDD::Result
|
11
|
-
attr_reader :
|
13
|
+
attr_reader :_type, :value, :subject
|
12
14
|
|
13
15
|
protected :subject
|
14
16
|
|
15
17
|
def initialize(type:, value:, subject: nil)
|
16
|
-
@
|
18
|
+
@_type = Type.new(type)
|
17
19
|
@value = value
|
18
20
|
@subject = subject
|
19
21
|
end
|
20
22
|
|
23
|
+
def type
|
24
|
+
_type.to_sym
|
25
|
+
end
|
26
|
+
|
21
27
|
def success?(_type = nil)
|
22
28
|
raise Error::NotImplemented
|
23
29
|
end
|
@@ -46,15 +52,15 @@ class BCDD::Result
|
|
46
52
|
def on(*types)
|
47
53
|
raise Error::MissingTypeArgument if types.empty?
|
48
54
|
|
49
|
-
tap { yield(value, type) if
|
55
|
+
tap { yield(value, type) if _type.in?(types, allow_empty: false) }
|
50
56
|
end
|
51
57
|
|
52
58
|
def on_success(*types)
|
53
|
-
tap { yield(value, type) if success? &&
|
59
|
+
tap { yield(value, type) if success? && _type.in?(types, allow_empty: true) }
|
54
60
|
end
|
55
61
|
|
56
62
|
def on_failure(*types)
|
57
|
-
tap { yield(value, type) if failure? &&
|
63
|
+
tap { yield(value, type) if failure? && _type.in?(types, allow_empty: true) }
|
58
64
|
end
|
59
65
|
|
60
66
|
def and_then(method_name = nil)
|
@@ -67,20 +73,20 @@ class BCDD::Result
|
|
67
73
|
ensure_result_object(result, origin: :block)
|
68
74
|
end
|
69
75
|
|
76
|
+
def handle
|
77
|
+
handler = Handler.new(self)
|
78
|
+
|
79
|
+
yield handler
|
80
|
+
|
81
|
+
handler.send(:outcome)
|
82
|
+
end
|
83
|
+
|
70
84
|
alias data value
|
71
85
|
alias data_or value_or
|
72
86
|
alias on_type on
|
73
87
|
|
74
88
|
private
|
75
89
|
|
76
|
-
def expected_type?(types)
|
77
|
-
types.any?(type)
|
78
|
-
end
|
79
|
-
|
80
|
-
def allowed_to_handle?(types)
|
81
|
-
types.empty? || expected_type?(types)
|
82
|
-
end
|
83
|
-
|
84
90
|
def call_subject_method(method_name)
|
85
91
|
method = subject.method(method_name)
|
86
92
|
|
data/sig/bcdd/result.rbs
CHANGED
@@ -5,12 +5,14 @@ module BCDD
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class BCDD::Result
|
8
|
-
attr_reader
|
8
|
+
attr_reader _type: BCDD::Result::Type
|
9
9
|
attr_reader value: untyped
|
10
10
|
attr_reader subject: untyped
|
11
11
|
|
12
12
|
def initialize: (type: Symbol, value: untyped, ?subject: untyped) -> void
|
13
13
|
|
14
|
+
def type: -> Symbol
|
15
|
+
|
14
16
|
def success?: (?Symbol type) -> bool
|
15
17
|
def failure?: (?Symbol type) -> bool
|
16
18
|
|
@@ -29,14 +31,14 @@ class BCDD::Result
|
|
29
31
|
|
30
32
|
def and_then: (?Symbol method_name) { (untyped) -> untyped } -> BCDD::Result
|
31
33
|
|
34
|
+
def handle: { (BCDD::Result::Handler) -> void } -> untyped
|
35
|
+
|
32
36
|
alias data value
|
33
37
|
alias data_or value_or
|
34
38
|
alias on_type on
|
35
39
|
|
36
40
|
private
|
37
41
|
|
38
|
-
def expected_type?: (Array[Symbol]) -> bool
|
39
|
-
def allowed_to_handle?: (Array[Symbol]) -> bool
|
40
42
|
def call_subject_method: (Symbol) -> BCDD::Result
|
41
43
|
def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result
|
42
44
|
end
|
@@ -55,6 +57,31 @@ class BCDD::Result
|
|
55
57
|
def self.Failure: (Symbol type, ?untyped value) -> BCDD::Result::Failure
|
56
58
|
end
|
57
59
|
|
60
|
+
class BCDD::Result
|
61
|
+
class Handler
|
62
|
+
UNDEFINED: Object
|
63
|
+
|
64
|
+
def initialize: (BCDD::Result) -> void
|
65
|
+
|
66
|
+
def []: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
67
|
+
def failure: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
68
|
+
def success: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
69
|
+
|
70
|
+
alias type []
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader _type: BCDD::Result::Type
|
75
|
+
attr_reader result: BCDD::Result
|
76
|
+
|
77
|
+
def outcome?: -> bool
|
78
|
+
|
79
|
+
def outcome: -> untyped
|
80
|
+
|
81
|
+
def outcome=: (Proc) -> void
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
58
85
|
module BCDD
|
59
86
|
module Resultable
|
60
87
|
def Success: (Symbol type, ?untyped value) -> BCDD::Result::Success
|
@@ -63,6 +90,16 @@ module BCDD
|
|
63
90
|
end
|
64
91
|
end
|
65
92
|
|
93
|
+
class BCDD::Result
|
94
|
+
class Type
|
95
|
+
attr_reader to_sym: Symbol
|
96
|
+
|
97
|
+
def initialize: (Symbol) -> void
|
98
|
+
|
99
|
+
def in?: (Array[Symbol], allow_empty: bool) -> bool
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
66
103
|
class BCDD::Result
|
67
104
|
class Error < ::StandardError
|
68
105
|
def self.build: (**untyped) -> BCDD::Result::Error
|
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.3.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-09-
|
11
|
+
date: 2023-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A general-purpose result monad that allows you to create objects that
|
14
14
|
represent a success (BCDD::Result::Success) or failure (BCDD::Result::Failure).
|
@@ -29,7 +29,9 @@ files:
|
|
29
29
|
- lib/bcdd/result.rb
|
30
30
|
- lib/bcdd/result/error.rb
|
31
31
|
- lib/bcdd/result/failure.rb
|
32
|
+
- lib/bcdd/result/handler.rb
|
32
33
|
- lib/bcdd/result/success.rb
|
34
|
+
- lib/bcdd/result/type.rb
|
33
35
|
- lib/bcdd/result/version.rb
|
34
36
|
- lib/bcdd/resultable.rb
|
35
37
|
- sig/bcdd/result.rbs
|