bcdd-result 0.7.0 → 0.8.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 +7 -0
- data/CHANGELOG.md +120 -0
- data/README.md +315 -133
- data/Rakefile +9 -3
- data/Steepfile +1 -1
- data/lib/bcdd/result/config/constant_alias.rb +33 -0
- data/lib/bcdd/result/config/options.rb +26 -0
- data/lib/bcdd/result/config/switcher.rb +82 -0
- data/lib/bcdd/result/config.rb +71 -0
- data/lib/bcdd/result/context/expectations/mixin.rb +5 -17
- data/lib/bcdd/result/context/expectations.rb +7 -23
- data/lib/bcdd/result/context/mixin.rb +12 -9
- data/lib/bcdd/result/contract/for_types_and_values.rb +7 -2
- data/lib/bcdd/result/contract.rb +4 -14
- data/lib/bcdd/result/expectations/mixin.rb +12 -10
- data/lib/bcdd/result/expectations.rb +31 -7
- data/lib/bcdd/result/mixin.rb +27 -14
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +11 -0
- data/lib/bcdd-result.rb +3 -0
- data/sig/bcdd/result.rbs +146 -38
- metadata +11 -8
- data/lib/result.rb +0 -5
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<h1 align="center" id="-bcddresult">🔀 BCDD::Result</h1>
|
3
|
-
<p align="center"><i>Empower Ruby apps with
|
3
|
+
<p align="center"><i>Empower Ruby apps with pragmatic use of Result monad, Railway Oriented Programming, and B/CDD.</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
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>
|
@@ -23,7 +23,7 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
23
23
|
- [`BCDD::Result` *versus* `Result`](#bcddresult-versus-result)
|
24
24
|
- [Reference](#reference)
|
25
25
|
- [Result Attributes](#result-attributes)
|
26
|
-
- [
|
26
|
+
- [Checking types with `result.success?` or `result.failure?`](#checking-types-with-resultsuccess-or-resultfailure)
|
27
27
|
- [Result Hooks](#result-hooks)
|
28
28
|
- [`result.on`](#resulton)
|
29
29
|
- [`result.on_type`](#resulton_type)
|
@@ -69,6 +69,12 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
69
69
|
- [Module example (Singleton Methods)](#module-example-singleton-methods-1)
|
70
70
|
- [`BCDD::Result::Context::Expectations`](#bcddresultcontextexpectations)
|
71
71
|
- [Mixin add-ons](#mixin-add-ons)
|
72
|
+
- [`BCDD::Result.configuration`](#bcddresultconfiguration)
|
73
|
+
- [`config.addon.enable!(:continue)`](#configaddonenablecontinue)
|
74
|
+
- [`config.constant_alias.enable!('Result')`](#configconstant_aliasenableresult)
|
75
|
+
- [`config.pattern_matching.disable!(:nil_as_valid_value_checking)`](#configpattern_matchingdisablenil_as_valid_value_checking)
|
76
|
+
- [`config.feature.disable!(:expectations)`](#configfeaturedisableexpectations)
|
77
|
+
- [`BCDD::Result.config`](#bcddresultconfig)
|
72
78
|
- [About](#about)
|
73
79
|
- [Development](#development)
|
74
80
|
- [Contributing](#contributing)
|
@@ -84,7 +90,7 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
|
|
84
90
|
Add this line to your application's Gemfile:
|
85
91
|
|
86
92
|
```ruby
|
87
|
-
gem 'bcdd-result'
|
93
|
+
gem 'bcdd-result'
|
88
94
|
```
|
89
95
|
|
90
96
|
And then execute:
|
@@ -95,6 +101,10 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
95
101
|
|
96
102
|
$ gem install bcdd-result
|
97
103
|
|
104
|
+
And require it in your code:
|
105
|
+
|
106
|
+
require 'bcdd/result'
|
107
|
+
|
98
108
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
99
109
|
|
100
110
|
## Usage
|
@@ -119,17 +129,27 @@ BCDD::Result::Failure(:err) #
|
|
119
129
|
|
120
130
|
#### `BCDD::Result` *versus* `Result`
|
121
131
|
|
122
|
-
|
132
|
+
This gem provides a way to create constant aliases for `BCDD::Result` and other classes/modules.
|
123
133
|
|
124
|
-
|
134
|
+
To enable it, you must call the `BCDD::Result.configuration` method and pass a block to it. You can turn the aliases you want on/off in this block.
|
125
135
|
|
126
136
|
```ruby
|
127
|
-
|
137
|
+
BCDD::Result.configuration do |config|
|
138
|
+
config.constant_alias.enable!('Result')
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
So, instead of using `BCDD::Result` everywhere, you can use `Result` as an alias/shortcut.
|
128
143
|
|
144
|
+
```ruby
|
129
145
|
Result::Success(:ok) # <BCDD::Result::Success type=:ok value=nil>
|
146
|
+
|
147
|
+
Result::Failure(:err) # <BCDD::Result::Failure type=:err value=nil>
|
130
148
|
```
|
131
149
|
|
132
|
-
|
150
|
+
If you have enabled constant aliasing, all examples in this README that use `BCDD::Result` can be implemented using `Result`.
|
151
|
+
|
152
|
+
There are other aliases and configurations available. Check the [BCDD::Result.configuration]() section for more information.
|
133
153
|
|
134
154
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
135
155
|
|
@@ -169,12 +189,12 @@ result.value # nil
|
|
169
189
|
################
|
170
190
|
# With a value #
|
171
191
|
################
|
172
|
-
result = BCDD::Result::Failure(:err,
|
192
|
+
result = BCDD::Result::Failure(:err, 'my_value')
|
173
193
|
|
174
194
|
result.success? # false
|
175
195
|
result.failure? # true
|
176
196
|
result.type # :err
|
177
|
-
result.value #
|
197
|
+
result.value # "my_value"
|
178
198
|
|
179
199
|
###################
|
180
200
|
# Without a value #
|
@@ -187,9 +207,11 @@ result.type # :no
|
|
187
207
|
result.value # nil
|
188
208
|
```
|
189
209
|
|
210
|
+
In both cases, the `type` must be a symbol, and the `value` can be any kind of object.
|
211
|
+
|
190
212
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
191
213
|
|
192
|
-
####
|
214
|
+
#### Checking types with `result.success?` or `result.failure?`
|
193
215
|
|
194
216
|
`BCDD::Result#success?` and `BCDD::Result#failure?` are methods that allow you to check if the result is a success or a failure.
|
195
217
|
|
@@ -198,9 +220,11 @@ You can also check the result type by passing an argument to it. For example, `r
|
|
198
220
|
```ruby
|
199
221
|
result = BCDD::Result::Success(:ok)
|
200
222
|
|
201
|
-
result.success?
|
202
|
-
|
203
|
-
|
223
|
+
result.success?(:ok)
|
224
|
+
|
225
|
+
# This is the same as:
|
226
|
+
|
227
|
+
result.success? && result.type == :ok
|
204
228
|
```
|
205
229
|
|
206
230
|
The same is valid for `BCDD::Result#failure?`.
|
@@ -208,9 +232,11 @@ The same is valid for `BCDD::Result#failure?`.
|
|
208
232
|
```ruby
|
209
233
|
result = BCDD::Result::Failure(:err)
|
210
234
|
|
211
|
-
result.failure?
|
212
|
-
|
213
|
-
|
235
|
+
result.failure?(:err)
|
236
|
+
|
237
|
+
# This is the same as:
|
238
|
+
|
239
|
+
result.failure? && result.type == :err
|
214
240
|
```
|
215
241
|
|
216
242
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
@@ -218,7 +244,7 @@ result.failure?(:error) # false
|
|
218
244
|
### Result Hooks
|
219
245
|
|
220
246
|
Result hooks are methods that allow you to execute a block of code based on the type of result obtained.
|
221
|
-
To demonstrate their use, I will implement a
|
247
|
+
To demonstrate their use, I will implement a method that can divide two numbers.
|
222
248
|
|
223
249
|
```ruby
|
224
250
|
def divide(arg1, arg2)
|
@@ -282,8 +308,7 @@ result = divide(nil, 2)
|
|
282
308
|
|
283
309
|
output =
|
284
310
|
result
|
285
|
-
.on_type(:invalid_arg) { |msg| puts msg }
|
286
|
-
.on_type(:division_by_zero) { |msg| puts msg }
|
311
|
+
.on_type(:invalid_arg, :division_by_zero) { |msg| puts msg }
|
287
312
|
.on_type(:division_completed) { |number| puts number }
|
288
313
|
|
289
314
|
# The code above will print 'arg1 must be numeric' and return the result itself.
|
@@ -303,16 +328,18 @@ The `BCDD::Result#on_success` method is quite similar to the `BCDD::Result#on` h
|
|
303
328
|
2. If the type declaration is not included, the method will execute the block for any successful result, regardless of its type.
|
304
329
|
|
305
330
|
```ruby
|
306
|
-
#
|
331
|
+
# In both examples, it executes the block and returns the result itself.
|
307
332
|
|
308
333
|
divide(4, 2).on_success { |number| puts number }
|
309
334
|
|
310
335
|
divide(4, 2).on_success(:division_completed) { |number| puts number }
|
311
336
|
|
312
|
-
# It doesn't execute the block
|
337
|
+
# It doesn't execute the block as the type is different.
|
313
338
|
|
314
339
|
divide(4, 4).on_success(:ok) { |value| puts value }
|
315
340
|
|
341
|
+
# It doesn't execute the block, as the result is a success, but the hook expects a failure.
|
342
|
+
|
316
343
|
divide(4, 4).on_failure { |error| puts error }
|
317
344
|
```
|
318
345
|
|
@@ -328,17 +355,19 @@ It is the opposite of `Result#on_success`:
|
|
328
355
|
2. If the type declaration is not included, the method will execute the block for any failed result, regardless of its type.
|
329
356
|
|
330
357
|
```ruby
|
331
|
-
#
|
358
|
+
# In both examples, it executes the block and returns the result itself.
|
332
359
|
|
333
360
|
divide(nil, 2).on_failure { |error| puts error }
|
334
361
|
|
335
|
-
divide(4, 0).on_failure(:
|
362
|
+
divide(4, 0).on_failure(:division_by_zero) { |error| puts error }
|
336
363
|
|
337
|
-
# It doesn't execute the block
|
338
|
-
|
339
|
-
divide(4, 0).on_success { |number| puts number }
|
364
|
+
# It doesn't execute the block as the type is different.
|
340
365
|
|
341
366
|
divide(4, 0).on_failure(:invalid_arg) { |error| puts error }
|
367
|
+
|
368
|
+
# It doesn't execute the block, as the result is a failure, but the hook expects a success.
|
369
|
+
|
370
|
+
divide(4, 0).on_success { |number| puts number }
|
342
371
|
```
|
343
372
|
|
344
373
|
*PS: The `divide()` implementation is [here](#result-hooks).*
|
@@ -570,7 +599,7 @@ module Divide
|
|
570
599
|
|
571
600
|
def call(arg1, arg2)
|
572
601
|
validate_numbers(arg1, arg2)
|
573
|
-
.and_then { |numbers|
|
602
|
+
.and_then { |numbers| validate_nonzero(numbers) }
|
574
603
|
.and_then { |numbers| divide(numbers) }
|
575
604
|
end
|
576
605
|
|
@@ -583,8 +612,8 @@ module Divide
|
|
583
612
|
BCDD::Result::Success(:ok, [arg1, arg2])
|
584
613
|
end
|
585
614
|
|
586
|
-
def
|
587
|
-
return BCDD::Result::Success(:ok, numbers)
|
615
|
+
def validate_nonzero(numbers)
|
616
|
+
return BCDD::Result::Success(:ok, numbers) if numbers.last.nonzero?
|
588
617
|
|
589
618
|
BCDD::Result::Failure(:division_by_zero, 'arg2 must not be zero')
|
590
619
|
end
|
@@ -615,9 +644,11 @@ Divide.call(2, 2)
|
|
615
644
|
|
616
645
|
#### `BCDD::Result.mixin`
|
617
646
|
|
618
|
-
This method generates a module that can
|
647
|
+
This method generates a module that any object can include or extend. It adds two methods to the target object: `Success()` and `Failure()`.
|
619
648
|
|
620
|
-
|
649
|
+
The main difference between these methods and `BCDD::Result::Success()`/`BCDD::Result::Failure()` is that the former will utilize the target object (which has received the include/extend) as the result's subject.
|
650
|
+
|
651
|
+
Because the result has a subject, the `#and_then` method can call methods from it.
|
621
652
|
|
622
653
|
##### Class example (Instance Methods)
|
623
654
|
|
@@ -634,7 +665,7 @@ class Divide
|
|
634
665
|
|
635
666
|
def call
|
636
667
|
validate_numbers
|
637
|
-
.and_then(:
|
668
|
+
.and_then(:validate_nonzero)
|
638
669
|
.and_then(:divide)
|
639
670
|
end
|
640
671
|
|
@@ -649,7 +680,7 @@ class Divide
|
|
649
680
|
Success(:ok, [arg1, arg2])
|
650
681
|
end
|
651
682
|
|
652
|
-
def
|
683
|
+
def validate_nonzero(numbers)
|
653
684
|
return Success(:ok, numbers) unless numbers.last.zero?
|
654
685
|
|
655
686
|
Failure(:division_by_zero, 'arg2 must not be zero')
|
@@ -675,7 +706,7 @@ module Divide
|
|
675
706
|
|
676
707
|
def call(arg1, arg2)
|
677
708
|
validate_numbers(arg1, arg2)
|
678
|
-
.and_then(:
|
709
|
+
.and_then(:validate_nonzero)
|
679
710
|
.and_then(:divide)
|
680
711
|
end
|
681
712
|
|
@@ -688,7 +719,7 @@ module Divide
|
|
688
719
|
Success(:ok, [arg1, arg2])
|
689
720
|
end
|
690
721
|
|
691
|
-
def
|
722
|
+
def validate_nonzero(numbers)
|
692
723
|
return Success(:ok, numbers) unless numbers.last.zero?
|
693
724
|
|
694
725
|
Failure(:division_by_zero, 'arg2 must not be zero')
|
@@ -717,7 +748,7 @@ If you try to use `BCDD::Result::Subject()`/`BCDD::Result::Failure()`, or result
|
|
717
748
|
**Note:** You can still use the block syntax, but all the results must be produced by the subject's `Success()` and `Failure()` methods.
|
718
749
|
|
719
750
|
```ruby
|
720
|
-
module
|
751
|
+
module ValidateNonzero
|
721
752
|
extend self, BCDD::Result.mixin
|
722
753
|
|
723
754
|
def call(numbers)
|
@@ -727,40 +758,83 @@ module ValidateNonZero
|
|
727
758
|
end
|
728
759
|
end
|
729
760
|
|
730
|
-
|
731
|
-
|
761
|
+
module Divide
|
762
|
+
extend self, BCDD::Result.mixin
|
732
763
|
|
733
|
-
|
764
|
+
def call(arg1, arg2)
|
765
|
+
validate_numbers(arg1, arg2)
|
766
|
+
.and_then(:validate_nonzero)
|
767
|
+
.and_then(:divide)
|
768
|
+
end
|
734
769
|
|
735
|
-
|
736
|
-
|
737
|
-
|
770
|
+
private
|
771
|
+
|
772
|
+
def validate_numbers(arg1, arg2)
|
773
|
+
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
|
774
|
+
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')
|
775
|
+
|
776
|
+
Success(:ok, [arg1, arg2])
|
738
777
|
end
|
739
778
|
|
740
|
-
def
|
741
|
-
|
742
|
-
|
779
|
+
def validate_nonzero(numbers)
|
780
|
+
ValidateNonzero.call(numbers) # This will raise an error
|
781
|
+
end
|
782
|
+
|
783
|
+
def divide((number1, number2))
|
784
|
+
Success(:division_completed, number1 / number2)
|
785
|
+
end
|
786
|
+
end
|
787
|
+
```
|
788
|
+
|
789
|
+
Look at the error produced by the code above:
|
790
|
+
|
791
|
+
```ruby
|
792
|
+
Divide.call(2, 0)
|
793
|
+
|
794
|
+
# You cannot call #and_then and return a result that does not belong to the subject! (BCDD::Result::Error::InvalidResultSubject)
|
795
|
+
# Expected subject: Divide
|
796
|
+
# Given subject: ValidateNonzero
|
797
|
+
# Given result: #<BCDD::Result::Failure type=:division_by_zero value="arg2 must not be zero">
|
798
|
+
```
|
799
|
+
|
800
|
+
In order to fix this, you must handle the result produced by `ValidateNonzero.call()` and return a result that belongs to the subject.
|
801
|
+
|
802
|
+
```ruby
|
803
|
+
module ValidateNonzero
|
804
|
+
extend self, BCDD::Result.mixin
|
805
|
+
|
806
|
+
def call(numbers)
|
807
|
+
return Success(:ok, numbers) unless numbers.last.zero?
|
808
|
+
|
809
|
+
Failure(:division_by_zero, 'arg2 must not be zero')
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
module Divide
|
814
|
+
extend self, BCDD::Result.mixin
|
815
|
+
|
816
|
+
def call(arg1, arg2)
|
817
|
+
validate_numbers(arg1, arg2)
|
818
|
+
.and_then(:validate_nonzero)
|
743
819
|
.and_then(:divide)
|
744
820
|
end
|
745
821
|
|
746
822
|
private
|
747
823
|
|
748
|
-
def validate_numbers
|
749
|
-
arg1.is_a?(::Numeric) or return
|
824
|
+
def validate_numbers(arg1, arg2)
|
825
|
+
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
|
750
826
|
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')
|
751
827
|
|
752
|
-
|
828
|
+
Success(:ok, [arg1, arg2])
|
753
829
|
end
|
754
830
|
|
755
|
-
def
|
756
|
-
ValidateNonZero.call(numbers) # This will raise an error
|
757
|
-
|
758
|
-
# This would work:
|
831
|
+
def validate_nonzero(numbers)
|
759
832
|
# In this case we are handling the other subject result and returning our own
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
833
|
+
ValidateNonzero.call(numbers).handle do |on|
|
834
|
+
on.success { |numbers| Success(:ok, numbers) }
|
835
|
+
|
836
|
+
on.failure { |err| Failure(:division_by_zero, err) }
|
837
|
+
end
|
764
838
|
end
|
765
839
|
|
766
840
|
def divide((number1, number2))
|
@@ -769,11 +843,20 @@ class Divide
|
|
769
843
|
end
|
770
844
|
```
|
771
845
|
|
846
|
+
Look at the output of the code above:
|
847
|
+
|
848
|
+
```ruby
|
849
|
+
Divide.call(2, 0)
|
850
|
+
|
851
|
+
#<BCDD::Result::Failure type=:division_by_zero value="arg2 must not be zero">
|
852
|
+
```
|
853
|
+
|
772
854
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
773
855
|
|
774
856
|
##### Dependency Injection
|
775
857
|
|
776
|
-
The `BCDD::Result#and_then` accepts a second argument that will be used to share a value with the subject's method.
|
858
|
+
The `BCDD::Result#and_then` accepts a second argument that will be used to share a value with the subject's method.
|
859
|
+
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.
|
777
860
|
|
778
861
|
```ruby
|
779
862
|
require 'logger'
|
@@ -783,7 +866,7 @@ module Divide
|
|
783
866
|
|
784
867
|
def call(arg1, arg2, logger: ::Logger.new(STDOUT))
|
785
868
|
validate_numbers(arg1, arg2)
|
786
|
-
.and_then(:
|
869
|
+
.and_then(:validate_nonzero, logger)
|
787
870
|
.and_then(:divide, logger)
|
788
871
|
end
|
789
872
|
|
@@ -796,7 +879,7 @@ module Divide
|
|
796
879
|
Success(:ok, [arg1, arg2])
|
797
880
|
end
|
798
881
|
|
799
|
-
def
|
882
|
+
def validate_nonzero(numbers, logger)
|
800
883
|
if numbers.last.zero?
|
801
884
|
logger.error('arg2 must not be zero')
|
802
885
|
|
@@ -830,19 +913,19 @@ Divide.call(4, 2, logger: Logger.new(IO::NULL))
|
|
830
913
|
|
831
914
|
##### Add-ons
|
832
915
|
|
833
|
-
The `BCDD::Result.mixin` also accepts the `
|
916
|
+
The `BCDD::Result.mixin` also accepts the `config:` argument. It is a hash that will be used to define custom behaviors for the mixin.
|
834
917
|
|
835
|
-
**
|
918
|
+
**continue**
|
836
919
|
|
837
920
|
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.
|
838
921
|
|
839
922
|
```ruby
|
840
923
|
module Divide
|
841
|
-
extend self, BCDD::Result.mixin(
|
924
|
+
extend self, BCDD::Result.mixin(config: { addon: { continue: true } })
|
842
925
|
|
843
926
|
def call(arg1, arg2)
|
844
927
|
validate_numbers(arg1, arg2)
|
845
|
-
.and_then(:
|
928
|
+
.and_then(:validate_nonzero)
|
846
929
|
.and_then(:divide)
|
847
930
|
end
|
848
931
|
|
@@ -855,7 +938,7 @@ module Divide
|
|
855
938
|
Continue([arg1, arg2])
|
856
939
|
end
|
857
940
|
|
858
|
-
def
|
941
|
+
def validate_nonzero(numbers)
|
859
942
|
return Continue(numbers) unless numbers.last.zero?
|
860
943
|
|
861
944
|
Failure(:division_by_zero, 'arg2 must not be zero')
|
@@ -904,11 +987,11 @@ Look what happens if you try to create a result without one of the expected type
|
|
904
987
|
```ruby
|
905
988
|
Divide::Result::Success(:ok)
|
906
989
|
# type :ok is not allowed. Allowed types: :numbers, :division_completed
|
907
|
-
# (BCDD::Result::
|
990
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
908
991
|
|
909
992
|
Divide::Result::Failure(:err)
|
910
993
|
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero
|
911
|
-
# (BCDD::Result::
|
994
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
912
995
|
```
|
913
996
|
|
914
997
|
The _**mixin mode**_ is similar to `BCDD::Result::Mixin`, but it also defines the expectations for the result's types and values.
|
@@ -922,7 +1005,7 @@ class Divide
|
|
922
1005
|
|
923
1006
|
def call(arg1, arg2)
|
924
1007
|
validate_numbers(arg1, arg2)
|
925
|
-
.and_then(:
|
1008
|
+
.and_then(:validate_nonzero)
|
926
1009
|
.and_then(:divide)
|
927
1010
|
end
|
928
1011
|
|
@@ -935,7 +1018,7 @@ class Divide
|
|
935
1018
|
Success(:numbers, [arg1, arg2])
|
936
1019
|
end
|
937
1020
|
|
938
|
-
def
|
1021
|
+
def validate_nonzero(numbers)
|
939
1022
|
return Success(:numbers, numbers) unless numbers.last.zero?
|
940
1023
|
|
941
1024
|
Failure(:division_by_zero, 'arg2 must not be zero')
|
@@ -947,10 +1030,10 @@ class Divide
|
|
947
1030
|
end
|
948
1031
|
```
|
949
1032
|
|
950
|
-
This mode also defines an `
|
1033
|
+
This mode also defines an `Result` constant to be used inside and outside the module.
|
951
1034
|
|
952
1035
|
> **PROTIP:**
|
953
|
-
> You can use the `
|
1036
|
+
> You can use the `Result` constant to mock the result's type and value in your tests. As they will have the exact expectations, your tests will check if the result clients are handling the result correctly.
|
954
1037
|
|
955
1038
|
Now that you know the two modes, let's understand how expectations can be beneficial and powerful for defining contracts.
|
956
1039
|
|
@@ -975,7 +1058,7 @@ result.success?(:division_completed) # true
|
|
975
1058
|
|
976
1059
|
result.success?(:ok)
|
977
1060
|
# type :ok is not allowed. Allowed types: :numbers, :division_completed
|
978
|
-
# (BCDD::Result::
|
1061
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
979
1062
|
```
|
980
1063
|
|
981
1064
|
**Failure example:**
|
@@ -989,7 +1072,7 @@ result.failure?(:division_by_zero) # false
|
|
989
1072
|
|
990
1073
|
result.failure?(:err)
|
991
1074
|
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero
|
992
|
-
# (BCDD::Result::
|
1075
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
993
1076
|
```
|
994
1077
|
|
995
1078
|
*PS: The `Divide` implementation is [here](#standalone-versus-mixin-mode).*
|
@@ -1011,7 +1094,7 @@ result
|
|
1011
1094
|
|
1012
1095
|
result.on(:number) { |_| :this_type_does_not_exist }
|
1013
1096
|
# type :number is not allowed. Allowed types: :numbers, :division_completed, :invalid_arg, :division_by_zero
|
1014
|
-
# (BCDD::Result::
|
1097
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1015
1098
|
```
|
1016
1099
|
|
1017
1100
|
*PS: The `Divide` implementation is [here](#standalone-versus-mixin-mode).*
|
@@ -1037,11 +1120,11 @@ result
|
|
1037
1120
|
|
1038
1121
|
result.on_success(:ok) { |_| :this_type_does_not_exist }
|
1039
1122
|
# type :ok is not allowed. Allowed types: :numbers, :division_completed
|
1040
|
-
# (BCDD::Result::
|
1123
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1041
1124
|
|
1042
1125
|
result.on_failure(:err) { |_| :this_type_does_not_exist }
|
1043
1126
|
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero
|
1044
|
-
# (BCDD::Result::
|
1127
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1045
1128
|
```
|
1046
1129
|
|
1047
1130
|
*PS: The `Divide` implementation is [here](#standalone-versus-mixin-mode).*
|
@@ -1058,17 +1141,17 @@ result = Divide.call(10, 2)
|
|
1058
1141
|
result.handle do |on|
|
1059
1142
|
on.type(:ok) { |_| :this_type_does_not_exist }
|
1060
1143
|
end
|
1061
|
-
# type :ok is not allowed. Allowed types: :numbers, :division_completed, :invalid_arg, :division_by_zero (BCDD::Result::
|
1144
|
+
# type :ok is not allowed. Allowed types: :numbers, :division_completed, :invalid_arg, :division_by_zero (BCDD::Result::Contract::Error::UnexpectedType)
|
1062
1145
|
|
1063
1146
|
result.handle do |on|
|
1064
1147
|
on.success(:ok) { |_| :this_type_does_not_exist }
|
1065
1148
|
end
|
1066
|
-
# type :ok is not allowed. Allowed types: :numbers, :division_completed (BCDD::Result::
|
1149
|
+
# type :ok is not allowed. Allowed types: :numbers, :division_completed (BCDD::Result::Contract::Error::UnexpectedType)
|
1067
1150
|
|
1068
1151
|
result.handle do |on|
|
1069
1152
|
on.failure(:err) { |_| :this_type_does_not_exist }
|
1070
1153
|
end
|
1071
|
-
# type :err is not allowed. Allowed types: :
|
1154
|
+
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero (BCDD::Result::Contract::Error::UnexpectedType)
|
1072
1155
|
```
|
1073
1156
|
|
1074
1157
|
*PS: The `Divide` implementation is [here](#standalone-versus-mixin-mode).*
|
@@ -1099,11 +1182,11 @@ end
|
|
1099
1182
|
|
1100
1183
|
Divide.call('4', 2)
|
1101
1184
|
# type :invalid_arg is not allowed. Allowed types: :err
|
1102
|
-
# (BCDD::Result::
|
1185
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1103
1186
|
|
1104
1187
|
Divide.call(4, 2)
|
1105
1188
|
# type :division_completed is not allowed. Allowed types: :ok
|
1106
|
-
# (BCDD::Result::
|
1189
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1107
1190
|
```
|
1108
1191
|
|
1109
1192
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
@@ -1126,11 +1209,11 @@ end
|
|
1126
1209
|
|
1127
1210
|
Divide.call('4', 2)
|
1128
1211
|
# type :invalid_arg is not allowed. Allowed types: :err
|
1129
|
-
# (BCDD::Result::
|
1212
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1130
1213
|
|
1131
1214
|
Divide.call(4, 2)
|
1132
1215
|
# type :division_completed is not allowed. Allowed types: :ok
|
1133
|
-
# (BCDD::Result::
|
1216
|
+
# (BCDD::Result::Contract::Error::UnexpectedType)
|
1134
1217
|
```
|
1135
1218
|
|
1136
1219
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
@@ -1201,26 +1284,26 @@ The value validation will only be performed through the methods `Success()` and
|
|
1201
1284
|
|
1202
1285
|
```ruby
|
1203
1286
|
Divide::Result::Success(:ok)
|
1204
|
-
# type :ok is not allowed. Allowed types: :numbers, :division_completed (BCDD::Result::
|
1287
|
+
# type :ok is not allowed. Allowed types: :numbers, :division_completed (BCDD::Result::Contract::Error::UnexpectedType)
|
1205
1288
|
|
1206
1289
|
Divide::Result::Success(:numbers, [1])
|
1207
|
-
# value [1] is not allowed for :numbers type (BCDD::Result::
|
1290
|
+
# value [1] is not allowed for :numbers type (BCDD::Result::Contract::Error::UnexpectedValue)
|
1208
1291
|
|
1209
1292
|
Divide::Result::Success(:division_completed, '2')
|
1210
|
-
# value "2" is not allowed for :division_completed type (BCDD::Result::
|
1293
|
+
# value "2" is not allowed for :division_completed type (BCDD::Result::Contract::Error::UnexpectedValue)
|
1211
1294
|
```
|
1212
1295
|
|
1213
1296
|
##### Failure()
|
1214
1297
|
|
1215
1298
|
```ruby
|
1216
1299
|
Divide::Result::Failure(:err)
|
1217
|
-
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero (BCDD::Result::
|
1300
|
+
# type :err is not allowed. Allowed types: :invalid_arg, :division_by_zero (BCDD::Result::Contract::Error::UnexpectedType)
|
1218
1301
|
|
1219
1302
|
Divide::Result::Failure(:invalid_arg, :arg1_must_be_numeric)
|
1220
|
-
# value :arg1_must_be_numeric is not allowed for :invalid_arg type (BCDD::Result::
|
1303
|
+
# value :arg1_must_be_numeric is not allowed for :invalid_arg type (BCDD::Result::Contract::Error::UnexpectedValue)
|
1221
1304
|
|
1222
1305
|
Divide::Result::Failure(:division_by_zero, msg: 'arg2 must not be zero')
|
1223
|
-
# value {:msg=>"arg2 must not be zero"} is not allowed for :division_by_zero type (BCDD::Result::
|
1306
|
+
# value {:msg=>"arg2 must not be zero"} is not allowed for :division_by_zero type (BCDD::Result::Contract::Error::UnexpectedValue)
|
1224
1307
|
```
|
1225
1308
|
|
1226
1309
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
@@ -1231,21 +1314,14 @@ The value checking has support for handling pattern-matching errors, and the cle
|
|
1231
1314
|
|
1232
1315
|
How does this operator work? They raise an error when the pattern does not match but returns nil when it matches.
|
1233
1316
|
|
1234
|
-
Because of this, you will need to enable `nil` as a valid value checking. You can do it
|
1235
|
-
|
1236
|
-
**Attention:**
|
1237
|
-
|
1238
|
-
If you decide to enable this, you will do it at the beginning of your code or in an initializer. And remember, this will affect all kinds of result expectations (`BCDD::Result::Expectations` and `BCDD::Result::Context::Expectations`). So, it is recommended to use it only when you are using pattern matching for **ALL** the result's value validations.
|
1317
|
+
Because of this, you will need to enable `nil` as a valid value checking. You can do it through the `BCDD::Result.configuration` or by allowing it directly on the mixin config.
|
1239
1318
|
|
1240
1319
|
```ruby
|
1241
|
-
#
|
1242
|
-
# Put this line in an initializer or at the beginning of your code.
|
1243
|
-
# It is required if you decide to use pattern matching to validate all of your result's values.
|
1244
|
-
#
|
1245
|
-
BCDD::Result::Contract.nil_as_valid_value_checking!
|
1246
|
-
|
1247
1320
|
module Divide
|
1248
1321
|
extend BCDD::Result::Expectations.mixin(
|
1322
|
+
config: {
|
1323
|
+
pattern_matching: { nil_as_valid_value_checking: true }
|
1324
|
+
},
|
1249
1325
|
success: {
|
1250
1326
|
division_completed: ->(value) { value => (Integer | Float) }
|
1251
1327
|
},
|
@@ -1263,30 +1339,30 @@ module Divide
|
|
1263
1339
|
end
|
1264
1340
|
|
1265
1341
|
Divide.call(10, 5)
|
1266
|
-
# value "
|
1342
|
+
# value "2" is not allowed for :division_completed type ("2": Float === "2" does not return true) (BCDD::Result::Contract::Error::UnexpectedValue)
|
1267
1343
|
```
|
1268
1344
|
|
1269
1345
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
1270
1346
|
|
1271
1347
|
#### `BCDD::Result::Expectations.mixin` add-ons
|
1272
1348
|
|
1273
|
-
The `BCDD::Result::Expectations.mixin` also accepts the `
|
1349
|
+
The `BCDD::Result::Expectations.mixin` also accepts the `config:` argument. It is a hash that can be used to define custom behaviors for the mixin.
|
1274
1350
|
|
1275
1351
|
**Continue**
|
1276
1352
|
|
1277
|
-
It is similar to `BCDD::Result.mixin(
|
1353
|
+
It is similar to `BCDD::Result.mixin(config: { addon: { continue: true } })`, 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.
|
1278
1354
|
|
1279
1355
|
```ruby
|
1280
1356
|
class Divide
|
1281
1357
|
include BCDD::Result::Expectations.mixin(
|
1282
|
-
|
1358
|
+
config: { addon: { continue: true } },
|
1283
1359
|
success: :division_completed,
|
1284
1360
|
failure: %i[invalid_arg division_by_zero]
|
1285
1361
|
)
|
1286
1362
|
|
1287
1363
|
def call(arg1, arg2)
|
1288
1364
|
validate_numbers(arg1, arg2)
|
1289
|
-
.and_then(:
|
1365
|
+
.and_then(:validate_nonzero)
|
1290
1366
|
.and_then(:divide)
|
1291
1367
|
end
|
1292
1368
|
|
@@ -1299,7 +1375,7 @@ class Divide
|
|
1299
1375
|
Continue([arg1, arg2])
|
1300
1376
|
end
|
1301
1377
|
|
1302
|
-
def
|
1378
|
+
def validate_nonzero(numbers)
|
1303
1379
|
return Continue(numbers) unless numbers.last.zero?
|
1304
1380
|
|
1305
1381
|
Failure(:division_by_zero, 'arg2 must not be zero')
|
@@ -1310,7 +1386,7 @@ class Divide
|
|
1310
1386
|
end
|
1311
1387
|
end
|
1312
1388
|
|
1313
|
-
result = Divide.new.call(4,2)
|
1389
|
+
result = Divide.new.call(4, 2)
|
1314
1390
|
# => #<BCDD::Result::Success type=:division_completed value=2>
|
1315
1391
|
|
1316
1392
|
# The example below shows an error because the :ok type is not allowed.
|
@@ -1318,7 +1394,7 @@ result = Divide.new.call(4,2)
|
|
1318
1394
|
# This is because the :continued type is ignored by the expectations.
|
1319
1395
|
#
|
1320
1396
|
result.success?(:ok)
|
1321
|
-
# type :ok is not allowed. Allowed types: :division_completed (BCDD::Result::
|
1397
|
+
# type :ok is not allowed. Allowed types: :division_completed (BCDD::Result::Contract::Error::UnexpectedType)
|
1322
1398
|
```
|
1323
1399
|
|
1324
1400
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
@@ -1368,14 +1444,14 @@ Let's see this feature and the data accumulation in action:
|
|
1368
1444
|
##### Class example (Instance Methods)
|
1369
1445
|
|
1370
1446
|
```ruby
|
1371
|
-
|
1372
|
-
require 'logger'
|
1447
|
+
require 'logger'
|
1373
1448
|
|
1449
|
+
class Divide
|
1374
1450
|
include BCDD::Result::Context.mixin
|
1375
1451
|
|
1376
1452
|
def call(arg1, arg2, logger: ::Logger.new(STDOUT))
|
1377
1453
|
validate_numbers(arg1, arg2)
|
1378
|
-
.and_then(:
|
1454
|
+
.and_then(:validate_nonzero)
|
1379
1455
|
.and_then(:divide, logger: logger)
|
1380
1456
|
end
|
1381
1457
|
|
@@ -1388,7 +1464,7 @@ class Divide
|
|
1388
1464
|
Success(:ok, number1: arg1, number2: arg2)
|
1389
1465
|
end
|
1390
1466
|
|
1391
|
-
def
|
1467
|
+
def validate_nonzero(number2:, **)
|
1392
1468
|
return Success(:ok) if number2.nonzero?
|
1393
1469
|
|
1394
1470
|
Failure(:err, message: 'arg2 must not be zero')
|
@@ -1434,8 +1510,9 @@ class Divide
|
|
1434
1510
|
|
1435
1511
|
def call(arg1, arg2)
|
1436
1512
|
validate_numbers(arg1, arg2)
|
1437
|
-
.and_then(:
|
1513
|
+
.and_then(:validate_nonzero)
|
1438
1514
|
.and_then(:divide)
|
1515
|
+
.and_expose(:division_completed, [:number])
|
1439
1516
|
end
|
1440
1517
|
|
1441
1518
|
private
|
@@ -1447,7 +1524,7 @@ class Divide
|
|
1447
1524
|
Success(:ok, number1: arg1, number2: arg2)
|
1448
1525
|
end
|
1449
1526
|
|
1450
|
-
def
|
1527
|
+
def validate_nonzero(number2:, **)
|
1451
1528
|
return Success(:ok) if number2.nonzero?
|
1452
1529
|
|
1453
1530
|
Failure(:err, message: 'arg2 must not be zero')
|
@@ -1483,7 +1560,7 @@ module Divide
|
|
1483
1560
|
|
1484
1561
|
def call(arg1, arg2)
|
1485
1562
|
validate_numbers(arg1, arg2)
|
1486
|
-
.and_then(:
|
1563
|
+
.and_then(:validate_nonzero)
|
1487
1564
|
.and_then(:divide)
|
1488
1565
|
.and_expose(:division_completed, [:number])
|
1489
1566
|
end
|
@@ -1497,7 +1574,7 @@ module Divide
|
|
1497
1574
|
Success(:ok, number1: arg1, number2: arg2)
|
1498
1575
|
end
|
1499
1576
|
|
1500
|
-
def
|
1577
|
+
def validate_nonzero(number2:, **)
|
1501
1578
|
return Success(:ok) if number2.nonzero?
|
1502
1579
|
|
1503
1580
|
Failure(:err, message: 'arg2 must not be zero')
|
@@ -1530,14 +1607,11 @@ The `BCDD::Result::Context::Expectations` is a `BCDD::Result::Expectations` with
|
|
1530
1607
|
This is an example using the mixin mode, but the standalone mode is also supported.
|
1531
1608
|
|
1532
1609
|
```ruby
|
1533
|
-
#
|
1534
|
-
# Put this line in an initializer or at the beginning of your code.
|
1535
|
-
# It is required if you decide to use pattern matching to validate all of your result's values.
|
1536
|
-
#
|
1537
|
-
BCDD::Result::Contract.nil_as_valid_value_checking!
|
1538
|
-
|
1539
1610
|
class Divide
|
1540
1611
|
include BCDD::Result::Context::Expectations.mixin(
|
1612
|
+
config: {
|
1613
|
+
pattern_matching: { nil_as_valid_value_checking: true }
|
1614
|
+
},
|
1541
1615
|
success: {
|
1542
1616
|
division_completed: ->(value) { value => { number: Numeric } }
|
1543
1617
|
},
|
@@ -1553,7 +1627,7 @@ class Divide
|
|
1553
1627
|
|
1554
1628
|
arg2.zero? and return Failure(:division_by_zero, message: 'arg2 must not be zero')
|
1555
1629
|
|
1556
|
-
Success(:division_completed, number: arg1 / arg2)
|
1630
|
+
Success(:division_completed, number: (arg1 / arg2))
|
1557
1631
|
end
|
1558
1632
|
end
|
1559
1633
|
|
@@ -1577,26 +1651,23 @@ Divide::Result::Success(:division_completed, number: '2')
|
|
1577
1651
|
|
1578
1652
|
#### Mixin add-ons
|
1579
1653
|
|
1580
|
-
The `BCDD::Result::Context.mixin` and `BCDD::Result::Context::Expectations.mixin` also accepts the `
|
1654
|
+
The `BCDD::Result::Context.mixin` and `BCDD::Result::Context::Expectations.mixin` also accepts the `config:` argument. And it works the same way as the `BCDD::Result` mixins.
|
1581
1655
|
|
1582
1656
|
**Continue**
|
1583
1657
|
|
1584
|
-
The `BCDD::Result::Context.mixin(
|
1658
|
+
The `BCDD::Result::Context.mixin(config: { addon: { continue: true } })` or `BCDD::Result::Context::Expectations.mixin(config: { addon: { continue: true } })` adds a `Continue(**input)` that will be ignored by the expectations. This is extremely useful when you want to use `Continue()` to chain operations, but you don't want to declare N success types in the expectations.
|
1585
1659
|
|
1586
1660
|
Let's use a mix of `BCDD::Result::Context` features to see in action with this add-on:
|
1587
1661
|
|
1588
1662
|
```ruby
|
1589
|
-
#
|
1590
|
-
# Put this line in an initializer or at the beginning of your code.
|
1591
|
-
# It is required if you decide to use pattern matching to validate all of your result's values.
|
1592
|
-
#
|
1593
|
-
BCDD::Result::Contract.nil_as_valid_value_checking!
|
1594
|
-
|
1595
1663
|
module Divide
|
1596
1664
|
require 'logger'
|
1597
1665
|
|
1598
1666
|
extend self, BCDD::Result::Context::Expectations.mixin(
|
1599
|
-
|
1667
|
+
config: {
|
1668
|
+
addon: { continue: true },
|
1669
|
+
pattern_matching: { nil_as_valid_value_checking: true }
|
1670
|
+
},
|
1600
1671
|
success: {
|
1601
1672
|
division_completed: ->(value) { value => { number: Numeric } }
|
1602
1673
|
},
|
@@ -1608,7 +1679,7 @@ module Divide
|
|
1608
1679
|
|
1609
1680
|
def call(arg1, arg2, logger: ::Logger.new(STDOUT))
|
1610
1681
|
validate_numbers(arg1, arg2)
|
1611
|
-
.and_then(:
|
1682
|
+
.and_then(:validate_nonzero)
|
1612
1683
|
.and_then(:divide, logger: logger)
|
1613
1684
|
.and_expose(:division_completed, [:number])
|
1614
1685
|
end
|
@@ -1622,7 +1693,7 @@ module Divide
|
|
1622
1693
|
Continue(number1: arg1, number2: arg2)
|
1623
1694
|
end
|
1624
1695
|
|
1625
|
-
def
|
1696
|
+
def validate_nonzero(number2:, **)
|
1626
1697
|
return Continue() if number2.nonzero?
|
1627
1698
|
|
1628
1699
|
Failure(:division_by_zero, message: 'arg2 must not be zero')
|
@@ -1651,8 +1722,119 @@ Divide.call(14, 0)
|
|
1651
1722
|
#<BCDD::Result::Context::Failure type=:division_by_zero value={:message=>"arg2 must not be zero"}>
|
1652
1723
|
```
|
1653
1724
|
|
1725
|
+
### `BCDD::Result.configuration`
|
1726
|
+
|
1727
|
+
The `BCDD::Result.configuration` allows you to configure default behaviors for `BCDD::Result` and `BCDD::Result::Context` through a configuration block. After using it, the configuration is frozen, ensuring the expected behaviors for your application.
|
1728
|
+
|
1729
|
+
```ruby
|
1730
|
+
BCDD::Result.configuration do |config|
|
1731
|
+
config.addon.enable!(:continue)
|
1732
|
+
|
1733
|
+
config.constant_alias.enable!('Result')
|
1734
|
+
|
1735
|
+
config.pattern_matching.disable!(:nil_as_valid_value_checking)
|
1736
|
+
|
1737
|
+
config.feature.disable!(:expectations) if ::Rails.env.production?
|
1738
|
+
end
|
1739
|
+
```
|
1740
|
+
|
1741
|
+
Use `disable!` to disable a feature and `enable!` to enable it.
|
1742
|
+
|
1743
|
+
Let's see what each configuration in the example above does:
|
1744
|
+
|
1745
|
+
#### `config.addon.enable!(:continue)`
|
1746
|
+
|
1747
|
+
This configuration enables the `Continue()` method for `BCDD::Result` and `BCDD::Result::Context`. Link to documentations: [(1)](#add-ons) [(2)](#mixin-add-ons).
|
1748
|
+
|
1749
|
+
#### `config.constant_alias.enable!('Result')`
|
1750
|
+
|
1751
|
+
This configuration make `Result` a constant alias for `BCDD::Result`. Link to [documentation](#bcddresult-versus-result).
|
1752
|
+
|
1753
|
+
#### `config.pattern_matching.disable!(:nil_as_valid_value_checking)`
|
1754
|
+
|
1755
|
+
This configuration disables the `nil_as_valid_value_checking` for `BCDD::Result` and `BCDD::Result::Context`. Link to [documentation](#pattern-matching-support).
|
1756
|
+
|
1654
1757
|
<p align="right"><a href="#-bcddresult">⬆️ back to top</a></p>
|
1655
1758
|
|
1759
|
+
#### `config.feature.disable!(:expectations)`
|
1760
|
+
|
1761
|
+
This configuration turns off the expectations for `BCDD::Result` and `BCDD::Result::Context`. The expectations are helpful in development and test environments, but they can be disabled in production environments for performance gain.
|
1762
|
+
|
1763
|
+
PS: I'm using `::Rails.env.production?` to check the environment, but you can use any logic you want.
|
1764
|
+
|
1765
|
+
### `BCDD::Result.config`
|
1766
|
+
|
1767
|
+
The `BCDD::Result.config` allows you to access the current configuration. It is useful when you want to check the current configuration.
|
1768
|
+
|
1769
|
+
**BCDD::Result.config.addon**
|
1770
|
+
|
1771
|
+
```ruby
|
1772
|
+
BCDD::Result.config.addon.enabled?(:continue)
|
1773
|
+
|
1774
|
+
BCDD::Result.config.addon.options
|
1775
|
+
# {
|
1776
|
+
# :continue=>{
|
1777
|
+
# :enabled=>false,
|
1778
|
+
# :affects=>[
|
1779
|
+
# "BCDD::Result",
|
1780
|
+
# "BCDD::Result::Context",
|
1781
|
+
# "BCDD::Result::Expectations",
|
1782
|
+
# "BCDD::Result::Context::Expectations"
|
1783
|
+
# ]
|
1784
|
+
# }
|
1785
|
+
# }
|
1786
|
+
```
|
1787
|
+
|
1788
|
+
**BCDD::Result.config.constant_alias**
|
1789
|
+
|
1790
|
+
```ruby
|
1791
|
+
BCDD::Result.config.constant_alias.enabled?('Result')
|
1792
|
+
|
1793
|
+
BCDD::Result.config.constant_alias.options
|
1794
|
+
# {
|
1795
|
+
# "Result"=>{
|
1796
|
+
# :enabled=>false,
|
1797
|
+
# :affects=>[
|
1798
|
+
# "Object"
|
1799
|
+
# ]
|
1800
|
+
# }
|
1801
|
+
# }
|
1802
|
+
```
|
1803
|
+
|
1804
|
+
**BCDD::Result.config.pattern_matching**
|
1805
|
+
|
1806
|
+
```ruby
|
1807
|
+
BCDD::Result.config.pattern_matching.enabled?(:nil_as_valid_value_checking)
|
1808
|
+
|
1809
|
+
BCDD::Result.config.pattern_matching.options
|
1810
|
+
# {
|
1811
|
+
# :nil_as_valid_value_checking=>{
|
1812
|
+
# :enabled=>false,
|
1813
|
+
# :affects=>[
|
1814
|
+
# "BCDD::Result::Expectations,
|
1815
|
+
# "BCDD::Result::Context::Expectations"
|
1816
|
+
# ]
|
1817
|
+
# }
|
1818
|
+
# }
|
1819
|
+
```
|
1820
|
+
|
1821
|
+
**BCDD::Result.config.feature**
|
1822
|
+
|
1823
|
+
```ruby
|
1824
|
+
BCDD::Result.config.feature.enabled?(:expectations)
|
1825
|
+
|
1826
|
+
BCDD::Result.config.feature.options
|
1827
|
+
# {
|
1828
|
+
# :expectations=>{
|
1829
|
+
# :enabled=>true,
|
1830
|
+
# :affects=>[
|
1831
|
+
# "BCDD::Result::Expectations,
|
1832
|
+
# "BCDD::Result::Context::Expectations"
|
1833
|
+
# ]
|
1834
|
+
# }
|
1835
|
+
# }
|
1836
|
+
```
|
1837
|
+
|
1656
1838
|
## About
|
1657
1839
|
|
1658
1840
|
[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.
|