consequence 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +90 -21
- data/lib/consequence.rb +1 -0
- data/lib/consequence/core_ext/m_alias.rb +3 -0
- data/lib/consequence/core_ext/private_symbol_proc.rb +9 -0
- data/lib/consequence/core_ext/utils.rb +5 -0
- data/lib/consequence/monad.rb +2 -2
- data/lib/consequence/something.rb +2 -0
- data/lib/consequence/success.rb +2 -0
- data/lib/consequence/utils.rb +8 -8
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3038f8d2f6c5083a3e945054dd080b655507ae47
|
4
|
+
data.tar.gz: 16ec4fc46d518cadd43564e87acb3bca08e4c8c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdf17369f753147abb4d225f9690e6206235f506d82a346987aee3c8b89f97084592a524d6a9ef6f2d9506936553793707987104d6d1f6b1df4df543483530d6
|
7
|
+
data.tar.gz: f79925766a50f40b0d63e62cc5dc5f39e4d53d48ea60a85161dabc292f247562eecb682a483cb0a39e1479f0fcf6aa3ad139d0698ac7f00bef03a188549d64dd
|
data/README.md
CHANGED
@@ -9,37 +9,38 @@ Simple monad implementation with clear and consistent syntax.
|
|
9
9
|
``` ruby
|
10
10
|
require 'consequence'
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
def process(i)
|
13
|
+
Foo[i] >> :next << log >> validate
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
increment = ->(v) { v + 1 }
|
16
|
+
def log
|
17
|
+
->(v) { puts v }
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
def validate
|
21
|
+
->(v, m) { m == Foo[5] ? m : Bar['Fail'] }
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
transform >> # Foo[10]
|
26
|
-
validate >> # Bar[10]
|
27
|
-
increment >> # Bar[11]
|
28
|
-
:next << react << log
|
24
|
+
Foo = Class.new(Consequence::Monad)
|
25
|
+
Bar = Class.new(Consequence::Monad)
|
29
26
|
|
30
|
-
p
|
31
|
-
p
|
27
|
+
p process(0) # Bar['Fail']
|
28
|
+
p process(4) # Foo[5]
|
32
29
|
```
|
33
30
|
|
34
31
|
## Operations
|
35
32
|
|
36
|
-
|
33
|
+
<dl>
|
34
|
+
<dt> >> Right Shift </dt>
|
35
|
+
<dd>Chains a proc with the result being passed along. If the result is not a monad, it is wrapped up in one.</dd>
|
37
36
|
|
38
|
-
|
37
|
+
<dt> << Left Shift </dt>
|
38
|
+
<dd>The supplied proc is applied with the result being ignored and the unchanged monad is passed down the chain.</dd>
|
39
|
+
</dl>
|
39
40
|
|
40
|
-
If the proc accepts one argument, it is passed only the `value` of the
|
41
|
+
If the proc accepts one argument, it is passed only the `value` of the monad. If it accepts two arguments, it is passed both the `value` and the monad.
|
41
42
|
|
42
|
-
Before being called, the proc have their `#to_proc` method called. This allows a `Symbol` to be passed in, whose `#to_proc` method sends the symbol as a message to the `value` of the
|
43
|
+
Before being called, the proc have their `#to_proc` method called. This allows a `Symbol` to be passed in, whose `#to_proc` method sends the symbol as a message to the `value` of the monad.
|
43
44
|
|
44
45
|
## Types
|
45
46
|
|
@@ -47,11 +48,79 @@ Before being called, the proc have their `#to_proc` method called. This allows a
|
|
47
48
|
|
48
49
|
A `Success` monad wraps up all exceptions in a `Failed` monad and a `Failed` monad ignores all chained methods. This allows all possible failures in a long process to be dealt with at the end.
|
49
50
|
|
51
|
+
``` ruby
|
52
|
+
require 'consequence'
|
53
|
+
|
54
|
+
module CreateUser
|
55
|
+
class << self
|
56
|
+
include Consequence
|
57
|
+
alias_method :m, :method
|
58
|
+
|
59
|
+
def create(attributes)
|
60
|
+
Success[attributes] >> m(:build) >> m(:validate) >> m(:persist)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def build(attributes)
|
66
|
+
User.new(attributes)
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate(user)
|
70
|
+
validator = UserValidator.new(user)
|
71
|
+
validator.valid? ? Success[user] : Failure[validator.errors]
|
72
|
+
end
|
73
|
+
|
74
|
+
def persist(user)
|
75
|
+
user.save
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
If the `User#new` raises an exception, the `validate` and `persist` methods won't be called, and a `Failure` monad will be returned with the exception as it's `value`.
|
82
|
+
|
83
|
+
If the `validator` finds the new user to be invalid, the `persist` method will not be called and a `Failure` monad will be returned with the errors as it's `value`.
|
84
|
+
|
50
85
|
### Something & Nothing
|
51
86
|
|
52
87
|
A `Something` monad wraps up a nil result in a `Nothing` monad and a `Nothing` monad ignores all chained methods. This prevents `MissingMethod` errors from trying to be call a method on `nil`.
|
53
88
|
|
54
|
-
|
89
|
+
## Utils
|
90
|
+
|
91
|
+
### `send_to_value` and `send_to_monad`
|
92
|
+
|
93
|
+
`send_to_value` and `send_to_monad` are utility methods that can be included from `Consequence::Utils`. They create procs that pass their arguments to the send method on the value and monad respectively.
|
94
|
+
|
95
|
+
``` ruby
|
96
|
+
include Consequence::Utils
|
97
|
+
|
98
|
+
Monad[2] << send_to_value(:**, 3) # Monad[8]
|
99
|
+
```
|
100
|
+
|
101
|
+
To include into Object to be available within all objects:
|
102
|
+
|
103
|
+
``` ruby
|
104
|
+
require 'consequence/core_ext/utils'
|
105
|
+
```
|
106
|
+
|
107
|
+
### `Object#m`
|
108
|
+
|
109
|
+
As a shorthand for the `Object#method` method, it can be useful to alias this to m, such as in the Success/Failure example. To do this for all objects:
|
110
|
+
|
111
|
+
``` ruby
|
112
|
+
require 'consequence/core_ext/m_alias'
|
113
|
+
```
|
114
|
+
|
115
|
+
### `Symbol#to_proc`
|
116
|
+
|
117
|
+
`Symbol#to_proc` can't be used to call private methods. This is inconvenient if you want an object to wrap itself up and call it's oen private methods with symbols. To use that style of notation, you can add this:
|
118
|
+
|
119
|
+
``` ruby
|
120
|
+
require 'consequence/core_ext/private_symbol_proc'
|
121
|
+
```
|
122
|
+
|
123
|
+
Alternatively, you can use `object#method`.
|
55
124
|
|
56
125
|
## Installation
|
57
126
|
|
data/lib/consequence.rb
CHANGED
data/lib/consequence/monad.rb
CHANGED
@@ -28,7 +28,7 @@ module Consequence
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def inspect
|
31
|
-
"#{self.class}[#{value}]"
|
31
|
+
"#{self.class}[#{value.inspect}]"
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
@@ -38,7 +38,7 @@ module Consequence
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def args_for(proc)
|
41
|
-
|
41
|
+
[value, self][0, proc.arity.abs]
|
42
42
|
end
|
43
43
|
|
44
44
|
def wrap(value)
|
data/lib/consequence/success.rb
CHANGED
data/lib/consequence/utils.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Consequence
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Utils
|
3
|
+
def send_to_value(*args)
|
4
|
+
->(v) { v.send(*args) }
|
5
|
+
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def send_to_monad(*args)
|
8
|
+
->(v, m) { m.send(*args) }
|
9
|
+
end
|
10
|
+
end
|
11
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consequence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -39,6 +39,9 @@ files:
|
|
39
39
|
- LICENSE.txt
|
40
40
|
- README.md
|
41
41
|
- lib/consequence.rb
|
42
|
+
- lib/consequence/core_ext/m_alias.rb
|
43
|
+
- lib/consequence/core_ext/private_symbol_proc.rb
|
44
|
+
- lib/consequence/core_ext/utils.rb
|
42
45
|
- lib/consequence/monad.rb
|
43
46
|
- lib/consequence/something.rb
|
44
47
|
- lib/consequence/success.rb
|