deterministic 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ef26aa56b5cda71158ead5307f6073ea135da19
4
- data.tar.gz: 6c636a3b653ab6ca860bfebfd647c4c033e39747
3
+ metadata.gz: 02fd1f0c22527cf4af1af78fdb8e868d4947fb3b
4
+ data.tar.gz: 0efb14c1c44f3d487e551765a1fb671b8e9b55c7
5
5
  SHA512:
6
- metadata.gz: 52f36a2df48c9e9deb4a1ab593eed996a17a8e8a59e3d4eef65a43de59346e6587655c1cf8a1219c23fc7a7de7498af76b2becfb511bf696f724b7f0debbbb17
7
- data.tar.gz: 267ef98b4a0f22ead89a91438a777d74c27aa188495245e2e5a143790948c265f2de7caaed5e3c901e64281a42d20d4a1aa792c4cdc65ba17390b35f331b0d8b
6
+ metadata.gz: cb9ab93ae058be25b8f724d4c246138ce6f576cf59f6bcf8e6927a97fbbd67f42fff1a527f7bcf791d858fd03d1108a8f756457a3bb0b345c82b5aa83c5ef7d2
7
+ data.tar.gz: a40bc7baf45c6785b0204faca45f9e5c3a4eb4f33e0baae1c647da5591bc464051bb58f8b109c09518c6aad80ae1f112d5a7659ea0df1d721db3d3ae38d55e86
data/Guardfile CHANGED
@@ -1,9 +1,13 @@
1
+ guard :bundler do
2
+ watch('Gemfile')
3
+ end
4
+
1
5
  guard :bundler do
2
6
  watch('Gemfile')
3
7
  watch(/^.+\.gemspec/)
4
8
  end
5
9
 
6
- guard :rspec do
10
+ guard :rspec, cmd: 'bundle exec rspec' do
7
11
  watch(%r{^spec/.+_spec\.rb$})
8
12
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
13
  watch('spec/spec_helper.rb') { "spec" }
@@ -12,4 +16,3 @@ guard :rspec do
12
16
  watch(%r{^spec/acceptance/(.+)\.feature$})
13
17
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
14
18
  end
15
-
data/README.md CHANGED
@@ -47,10 +47,70 @@ Failure(1).or_else { |v| Success(v)} # => Success(1)
47
47
 
48
48
  The value or block result must always be a `Success` or `Failure`
49
49
 
50
+ ### Either.chain
51
+ You can easily chain the execution of several operations. Here we got some nice function composition.
52
+ The method must be a unary function, i.e. it always takes one parameter - the context, which is passed from call to call.
50
53
 
54
+ ```ruby
55
+ class Foo
56
+ include Deterministic
57
+ alias :m :method
58
+
59
+ def call
60
+ setup >> m(:validate) >> m(:send)
61
+ end
62
+
63
+ def setup
64
+ Success(1)
65
+ end
66
+
67
+ def validate(ctx)
68
+ # do stuff
69
+ Success(ctx + 1)
70
+ end
71
+
72
+ def send(ctx)
73
+ # do stuff
74
+ Success(ctx + 1)
75
+ end
76
+ end
77
+
78
+ Foo.new.call # Success(3)
79
+ ```
80
+
81
+ Chaining works with blocks (`#chain` is an alias for `#>>`)
82
+
83
+ ```ruby
84
+ Success(1).chain {|ctx| Success(ctx + 1)}
85
+ ```
86
+
87
+ it also works with lambdas
88
+ ```ruby
89
+ Success(1) >> ->(ctx) { Success(ctx + 1) } >> ->(ctx) { Success(ctx + 1) }
90
+ ```
91
+
92
+ and it will break the chain of execution, when it encounters a `Failure` on its way
93
+
94
+ ```ruby
95
+ def works(ctx)
96
+ Success(1)
97
+ end
98
+
99
+ def breaks(ctx)
100
+ Failure(2)
101
+ end
102
+
103
+ def never_executed(ctx)
104
+ Success(99)
105
+ end
106
+
107
+ Success(0) >> method(:works) >> method(:breaks) >> method(:never_executed) # Failure(2)
108
+ ```
51
109
 
52
110
  ### Either.attempt_all
53
111
  The basic idea is to execute a chain of units of work and make sure all return either `Success` or `Failure`.
112
+ This remains for compatibility reasons, personally I would use the `>>` chaining.
113
+
54
114
 
55
115
  ```ruby
56
116
  Either.attempt_all do
@@ -0,0 +1,13 @@
1
+ module Deterministic
2
+ class Either
3
+ module Chain
4
+ def chain(proc=nil, &block)
5
+ return self if failure?
6
+ bind { (proc || block).call(@value) }
7
+ end
8
+
9
+ alias :>> :chain
10
+ end
11
+ end
12
+ end
13
+
@@ -3,6 +3,7 @@ module Deterministic
3
3
  class Either
4
4
  include Monad
5
5
  include Deterministic::PatternMatching
6
+ include Chain
6
7
 
7
8
  def bind(proc=nil, &block)
8
9
  (proc || block).call(value, self.class).tap do |result|
@@ -28,11 +29,6 @@ module Deterministic
28
29
  protected :new
29
30
  end
30
31
 
31
- def to_json(*args)
32
- name = self.class.name.split('::')[-1]
33
- "{\"#{name}\":#{value.to_json(*args)}}"
34
- end
35
-
36
32
  def to_s
37
33
  value.to_s
38
34
  end
@@ -1,3 +1,3 @@
1
1
  module Deterministic
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
data/lib/deterministic.rb CHANGED
@@ -6,6 +6,7 @@ module Deterministic; end
6
6
 
7
7
  require 'deterministic/monad'
8
8
  require 'deterministic/either/match'
9
+ require 'deterministic/either/chain'
9
10
  require 'deterministic/either'
10
11
  require 'deterministic/either/attempt_all'
11
12
  require 'deterministic/either/success'
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ include Deterministic
4
+
5
+ describe Deterministic::Either do
6
+ context ">>" do
7
+ it "Failure stops execution" do
8
+ class ChainUnderTest
9
+ alias :m :method
10
+
11
+ def call
12
+ init >> m(:validate) >> m(:send) >> m(:parse)
13
+ end
14
+
15
+ def init
16
+ Success({step: 1})
17
+ end
18
+
19
+ def validate(i)
20
+ i[:step] = i[:step] + 1
21
+ Success(i)
22
+ end
23
+
24
+ def send(i)
25
+ i[:step] = i[:step] + 1
26
+ Failure("Error @ #{i.fetch(:step)}")
27
+ end
28
+
29
+ def parse(i)
30
+ i[:step] = i[:step] + 1
31
+ Success(i)
32
+ end
33
+ end
34
+
35
+ test = ChainUnderTest.new
36
+
37
+ expect(test.call).to eq Failure("Error @ 3")
38
+ end
39
+
40
+ it "expects an Either" do
41
+ def returns_non_either(i)
42
+ 2
43
+ end
44
+
45
+ expect { Success(1) >> method(:returns_non_either) }.to raise_error(Deterministic::Monad::NotMonadError)
46
+ end
47
+
48
+ it "works with a block" do
49
+ expect(
50
+ Success(1).chain { |i| Success(i + 1) }
51
+ ).to eq Success(2)
52
+ end
53
+
54
+ it "works with a lambda" do
55
+ expect(
56
+ Success(1) >> ->(i) { Success(i + 1) }
57
+ ).to eq Success(2)
58
+ end
59
+ end
60
+ end
@@ -11,10 +11,6 @@ shared_examples 'Either' do
11
11
  expect(either.new(1).bind { |v| either.new(v + 1)}).to eq either.new(2)
12
12
  end
13
13
 
14
- it "#to_json" do
15
- expect(either.new({a: 1}).to_json).to eq "{\"#{either_name}\":{\"a\":1}}"
16
- end
17
-
18
14
  it "#to_s" do
19
15
  expect(either.new(1).to_s).to eq "1"
20
16
  expect(either.new({a: 1}).to_s).to eq "{:a=>1}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deterministic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Zolnierek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2014-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -129,6 +129,7 @@ files:
129
129
  - lib/deterministic/core_ext/object/either.rb
130
130
  - lib/deterministic/either.rb
131
131
  - lib/deterministic/either/attempt_all.rb
132
+ - lib/deterministic/either/chain.rb
132
133
  - lib/deterministic/either/failure.rb
133
134
  - lib/deterministic/either/match.rb
134
135
  - lib/deterministic/either/success.rb
@@ -141,6 +142,7 @@ files:
141
142
  - spec/lib/deterministic/attempt_all_spec.rb
142
143
  - spec/lib/deterministic/core_ext/either_spec.rb
143
144
  - spec/lib/deterministic/core_ext/object/either_spec.rb
145
+ - spec/lib/deterministic/either/chain_spec.rb
144
146
  - spec/lib/deterministic/either/either_shared.rb
145
147
  - spec/lib/deterministic/either/failure_spec.rb
146
148
  - spec/lib/deterministic/either/match_spec.rb
@@ -181,6 +183,7 @@ test_files:
181
183
  - spec/lib/deterministic/attempt_all_spec.rb
182
184
  - spec/lib/deterministic/core_ext/either_spec.rb
183
185
  - spec/lib/deterministic/core_ext/object/either_spec.rb
186
+ - spec/lib/deterministic/either/chain_spec.rb
184
187
  - spec/lib/deterministic/either/either_shared.rb
185
188
  - spec/lib/deterministic/either/failure_spec.rb
186
189
  - spec/lib/deterministic/either/match_spec.rb