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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a41105b84f902004736a171bd42c943923ee188d14fe6630bf379fb3e3ef158
4
- data.tar.gz: 7b879ee4c04c2b60e95d1c2af18e28c8e7f1edb475c0cdb8274c56f6a577198a
3
+ metadata.gz: 96c58d6a9132fbf42fc8f3c1d9ba683f0b6297e23b1f0536fc4bcb7efb5084df
4
+ data.tar.gz: fcef45f3c5ddacc20ff5e9533012c7fbe5817878cef1ff528dabd8920e1cbccd
5
5
  SHA512:
6
- metadata.gz: 48e9dd67d1f69a4b9aae0bbf1166aab532ca2f8cdc8883bf303b5a41f702a77c8531c4ae2baa96bf256a828e9db0624d631c1259e0870c9ee22ecd65b4ed2ce9
7
- data.tar.gz: cb2a0e618b21a4bf98c61b0a4dabfac322efe4293eab18c84cf729df920c49bf47557dcf20ceb01c42ac7c4673fa6fb55c235a2e93f2555a2021cbbfb3f37b36
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-25 17:14:03 UTC using RuboCop version 1.56.3.
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
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
- Install the gem and add to the application's Gemfile by executing:
50
+ Add this line to your application's Gemfile:
45
51
 
46
- $ bundle add bcdd-result
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">⬆️ &nbsp;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">⬆️ &nbsp;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">⬆️ &nbsp;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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BCDD
4
4
  class Result
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
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 :type, :value, :subject
13
+ attr_reader :_type, :value, :subject
12
14
 
13
15
  protected :subject
14
16
 
15
17
  def initialize(type:, value:, subject: nil)
16
- @type = type.to_sym
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 expected_type?(types) }
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? && allowed_to_handle?(types) }
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? && allowed_to_handle?(types) }
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 type: Symbol
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.2.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-26 00:00:00.000000000 Z
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