deterministic 0.8.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +17 -0
- data/README.md +121 -153
- data/lib/deterministic/core_ext/object/result.rb +6 -0
- data/lib/deterministic/core_ext/{either.rb → result.rb} +2 -6
- data/lib/deterministic/monad.rb +3 -3
- data/lib/deterministic/result/chain.rb +27 -0
- data/lib/deterministic/result/failure.rb +5 -0
- data/lib/deterministic/{either → result}/match.rb +5 -5
- data/lib/deterministic/result/success.rb +5 -0
- data/lib/deterministic/{either.rb → result.rb} +29 -6
- data/lib/deterministic/version.rb +1 -1
- data/lib/deterministic.rb +5 -6
- data/spec/examples/bookings_spec.rb +3 -5
- data/spec/lib/deterministic/core_ext/object/either_spec.rb +3 -20
- data/spec/lib/deterministic/core_ext/result_spec.rb +22 -0
- data/spec/lib/deterministic/maybe_spec.rb +2 -0
- data/spec/lib/deterministic/monad_spec.rb +3 -3
- data/spec/lib/deterministic/result/chain_spec.rb +150 -0
- data/spec/lib/deterministic/{either → result}/failure_spec.rb +9 -6
- data/spec/lib/deterministic/{either → result}/match_spec.rb +5 -5
- data/spec/lib/deterministic/result/result_shared.rb +23 -0
- data/spec/lib/deterministic/{either → result}/success_spec.rb +10 -6
- data/spec/lib/deterministic/{either_spec.rb → result_spec.rb} +3 -3
- metadata +24 -27
- data/either.rb +0 -97
- data/lib/deterministic/core_ext/object/either.rb +0 -6
- data/lib/deterministic/either/attempt_all.rb +0 -50
- data/lib/deterministic/either/chain.rb +0 -22
- data/lib/deterministic/either/failure.rb +0 -22
- data/lib/deterministic/either/success.rb +0 -22
- data/spec/lib/deterministic/attempt_all_spec.rb +0 -115
- data/spec/lib/deterministic/core_ext/either_spec.rb +0 -50
- data/spec/lib/deterministic/either/chain_spec.rb +0 -80
- data/spec/lib/deterministic/either/either_shared.rb +0 -23
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
include Deterministic
|
4
|
-
|
5
|
-
describe Deterministic::Either::AttemptAll do
|
6
|
-
it "#try evaluates the result as Success" do
|
7
|
-
expect(
|
8
|
-
Either.attempt_all do
|
9
|
-
try { @a = 1 }
|
10
|
-
try { @b = @a + 1 }
|
11
|
-
end
|
12
|
-
).to eq Success(2)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "#try values are passed to the next command" do
|
16
|
-
expect(
|
17
|
-
Either.attempt_all do
|
18
|
-
try { 1 }
|
19
|
-
try { |v| v + 1 }
|
20
|
-
end
|
21
|
-
).to eq Success(2)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "try treat exceptions as Failure" do
|
25
|
-
attempt = Either.attempt_all do
|
26
|
-
try { 1 }
|
27
|
-
try { raise "error" }
|
28
|
-
end.value
|
29
|
-
expect(attempt).to be_a RuntimeError
|
30
|
-
expect(attempt.message).to eq "error"
|
31
|
-
end
|
32
|
-
|
33
|
-
it "don't continue on failure" do
|
34
|
-
fake = double()
|
35
|
-
expect(
|
36
|
-
Either.attempt_all do
|
37
|
-
try { 1 }
|
38
|
-
let { Failure(2) }
|
39
|
-
try { fake.should_not_be_called }
|
40
|
-
end
|
41
|
-
).to eq Failure(2)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "#let expects Success or Failure" do
|
45
|
-
expect(
|
46
|
-
Either.attempt_all do
|
47
|
-
let { Success(1) }
|
48
|
-
end
|
49
|
-
).to eq Success(1)
|
50
|
-
|
51
|
-
expect {
|
52
|
-
Either.attempt_all do
|
53
|
-
let { 1 }
|
54
|
-
end
|
55
|
-
}.to raise_error(Deterministic::Either::AttemptAll::EitherExpectedError)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "#let will not catch errors" do
|
59
|
-
expect {
|
60
|
-
Either.attempt_all do
|
61
|
-
let { raise "error" }
|
62
|
-
end
|
63
|
-
}.to raise_error
|
64
|
-
end
|
65
|
-
|
66
|
-
it "#let passes params unboxed" do
|
67
|
-
expect(
|
68
|
-
Either.attempt_all do
|
69
|
-
try { 1 }
|
70
|
-
let { |v| Success(v + 1) }
|
71
|
-
end
|
72
|
-
).to eq Success(2)
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
it "works with boxed values" do
|
77
|
-
expect(
|
78
|
-
Either.attempt_all do
|
79
|
-
try { Failure(1) }
|
80
|
-
try { 2 }
|
81
|
-
end
|
82
|
-
).to eq Failure(1)
|
83
|
-
end
|
84
|
-
|
85
|
-
it "works with an OpenStruct" do
|
86
|
-
context = OpenStruct.new
|
87
|
-
attempt = Either.attempt_all(context) do
|
88
|
-
let { Success(self.alpha = 2) }
|
89
|
-
try { self.res = 1 }
|
90
|
-
end
|
91
|
-
|
92
|
-
expect(context.res).to eq 1
|
93
|
-
expect(context.alpha).to eq 2
|
94
|
-
end
|
95
|
-
|
96
|
-
it "can operate in the context of a context" do
|
97
|
-
class Context
|
98
|
-
attr_accessor :a
|
99
|
-
def initialize
|
100
|
-
@a = 1
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context = Context.new
|
105
|
-
|
106
|
-
expect(
|
107
|
-
Either.attempt_all(context) do
|
108
|
-
try { self.a += 1 }
|
109
|
-
try { self.a + 1 }
|
110
|
-
end
|
111
|
-
).to eq Success(3)
|
112
|
-
|
113
|
-
expect(context.a).to eq 2
|
114
|
-
end
|
115
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "deterministic"
|
3
|
-
require "deterministic/core_ext/either"
|
4
|
-
|
5
|
-
describe Deterministic::CoreExt::Either do
|
6
|
-
it "does something" do
|
7
|
-
h = {}
|
8
|
-
h.extend(Deterministic::CoreExt::Either)
|
9
|
-
expect(h.success?).to be_falsey
|
10
|
-
expect(h.failure?).to be_falsey
|
11
|
-
expect(h.either?).to be_falsey
|
12
|
-
end
|
13
|
-
|
14
|
-
it "enables #success?, #failure?, #either? on all Objects" do
|
15
|
-
ary = [Deterministic::Success(true), Deterministic::Success(1)]
|
16
|
-
expect(ary.all?(&:success?)).to be_truthy
|
17
|
-
|
18
|
-
ary = [Deterministic::Success(true), Deterministic::Failure(1)]
|
19
|
-
expect(ary.all?(&:success?)).to be_falsey
|
20
|
-
expect(ary.any?(&:failure?)).to be_truthy
|
21
|
-
end
|
22
|
-
|
23
|
-
it "allows using attempt_all on all Objects" do
|
24
|
-
h = {a: 1}
|
25
|
-
h.extend(Deterministic::CoreExt::Either)
|
26
|
-
res = h.attempt_all do
|
27
|
-
try { |s| s[:a] + 1}
|
28
|
-
end
|
29
|
-
|
30
|
-
expect(res).to eq Deterministic::Success(2)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "use attempt_all in an instance" do
|
34
|
-
class UnderTest
|
35
|
-
include Deterministic::CoreExt::Either
|
36
|
-
def test
|
37
|
-
attempt_all do
|
38
|
-
try { foo }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def foo
|
43
|
-
1
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
ut = UnderTest.new
|
48
|
-
expect(ut.test).to eq Success(1)
|
49
|
-
end
|
50
|
-
end
|
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
include Deterministic
|
4
|
-
|
5
|
-
describe Deterministic::Either do
|
6
|
-
context ">> (chain)" do
|
7
|
-
it "Failure stops execution" do
|
8
|
-
class ChainUnderTest
|
9
|
-
alias :m :method
|
10
|
-
|
11
|
-
def call
|
12
|
-
init >>
|
13
|
-
m(:validate) >>
|
14
|
-
m(:send) >>
|
15
|
-
m(:parse)
|
16
|
-
end
|
17
|
-
|
18
|
-
def init
|
19
|
-
Success({step: 1})
|
20
|
-
end
|
21
|
-
|
22
|
-
def validate(i)
|
23
|
-
i[:step] = i[:step] + 1
|
24
|
-
Success(i)
|
25
|
-
end
|
26
|
-
|
27
|
-
def send(i)
|
28
|
-
i[:step] = i[:step] + 1
|
29
|
-
Failure("Error @ #{i.fetch(:step)}")
|
30
|
-
end
|
31
|
-
|
32
|
-
def parse(i)
|
33
|
-
i[:step] = i[:step] + 1
|
34
|
-
Success(i)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
test = ChainUnderTest.new
|
39
|
-
|
40
|
-
expect(test.call).to eq Failure("Error @ 3")
|
41
|
-
end
|
42
|
-
|
43
|
-
it "expects an Either" do
|
44
|
-
def returns_non_either(i)
|
45
|
-
2
|
46
|
-
end
|
47
|
-
|
48
|
-
expect { Success(1) >> method(:returns_non_either) }.to raise_error(Deterministic::Monad::NotMonadError)
|
49
|
-
end
|
50
|
-
|
51
|
-
it "works with a block" do
|
52
|
-
expect(
|
53
|
-
Success(1).chain { |i| Success(i + 1) }
|
54
|
-
).to eq Success(2)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "works with a lambda" do
|
58
|
-
expect(
|
59
|
-
Success(1) >> ->(i) { Success(i + 1) }
|
60
|
-
).to eq Success(2)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "does not catch exceptions" do
|
64
|
-
expect {
|
65
|
-
Success(1) >> ->(i) { raise "error" }
|
66
|
-
}.to raise_error(RuntimeError)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context ">= (try)" do
|
71
|
-
it "try (>=) catches errors and wraps them as Failure" do
|
72
|
-
def error(ctx)
|
73
|
-
raise "error #{ctx}"
|
74
|
-
end
|
75
|
-
|
76
|
-
actual = Success(1) >= method(:error)
|
77
|
-
expect(actual.inspect).to eq "Failure(error 1)"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
shared_examples 'Either' do
|
2
|
-
let(:either_name) { described_class.name.split("::")[-1]}
|
3
|
-
specify { expect(subject.value).to eq 1 }
|
4
|
-
specify { expect(either.new(subject)).to eq either.new(1) }
|
5
|
-
|
6
|
-
it "#map" do
|
7
|
-
expect(either.new(1).map { |e| e + 1 }).to eq either.new(2)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "#bind" do
|
11
|
-
expect(either.new(1).bind { |v| either.new(v + 1)}).to eq either.new(2)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "#to_s" do
|
15
|
-
expect(either.new(1).to_s).to eq "1"
|
16
|
-
expect(either.new({a: 1}).to_s).to eq "{:a=>1}"
|
17
|
-
end
|
18
|
-
|
19
|
-
it "#inspect" do
|
20
|
-
expect(either.new(1).inspect).to eq "#{either_name}(1)"
|
21
|
-
expect(either.new(:a=>1).inspect).to eq "#{either_name}({:a=>1})"
|
22
|
-
end
|
23
|
-
end
|