deterministic 0.7.1 → 0.8.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
  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