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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c2b7b3c259799b0b5a6c368a64a1f7bc0f12d6a
4
- data.tar.gz: e441c9585001b3c347f74d129eeac6273e8e9ecd
3
+ metadata.gz: 3038f8d2f6c5083a3e945054dd080b655507ae47
4
+ data.tar.gz: 16ec4fc46d518cadd43564e87acb3bca08e4c8c6
5
5
  SHA512:
6
- metadata.gz: 645626fc457cec8d73894930e7f94df018f71874c9766d39d5420a134d8d47024697b91cf1373ea997c1b6eca8435f1a0d0292f8be32951ea19c9cfbd79bd579
7
- data.tar.gz: 86b2c7ead5e669d41a84567799c313cfbe4892e9a868e826d31489bf238d3596ee5391ca767964f359decec147b6c77881ba54f8021018fb79cdaa47fe5d787d
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
- Foo = Class.new(Consequence::Monad)
13
- Bar = Class.new(Consequence::Monad)
12
+ def process(i)
13
+ Foo[i] >> :next << log >> validate
14
+ end
14
15
 
15
- compare = ->(v, m) { m == Foo[0] ? Foo[1] : Bar[v] }
16
- transform = ->(v, m) { m == Foo[1] ? 10 : 3 }
17
- validate = ->(v) { v > 4 ? Bar[v] : Foo[v] }
18
- increment = ->(v) { v + 1 }
16
+ def log
17
+ ->(v) { puts v }
18
+ end
19
19
 
20
- react = ->(v, m) { @side_effect = v ** 2 if m.is_a?(Bar) }
21
- log = ->(v) { @side_effect = @side_effect.to_s }
20
+ def validate
21
+ ->(v, m) { m == Foo[5] ? m : Bar['Fail'] }
22
+ end
22
23
 
23
- result = Foo[0] >>
24
- compare >> # Foo[1]
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 result # Bar[12]
31
- p @side_effect # "144"
27
+ p process(0) # Bar['Fail']
28
+ p process(4) # Foo[5]
32
29
  ```
33
30
 
34
31
  ## Operations
35
32
 
36
- * `>>` - Chains a proc with the result being passed along. If the result is not a `Monad`, it is wrapped up in one.
33
+ <dl>
34
+ <dt> &gt;&gt; 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
- * `<<` - The supplied proc is applied with the result being ignored and the unchanged `Monad` is passed down the chain.
37
+ <dt> &lt;&lt; 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 `Monad`. If it accepts two values, it is passed both the `value` and the `Monad`.
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 `Monad`.
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
- ### More to come...
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
@@ -2,5 +2,6 @@ module Consequence
2
2
  end
3
3
 
4
4
  require 'consequence/monad'
5
+ require 'consequence/utils'
5
6
  require 'consequence/success'
6
7
  require 'consequence/something'
@@ -0,0 +1,3 @@
1
+ class Object
2
+ alias_method :m, :method
3
+ end
@@ -0,0 +1,9 @@
1
+ # This allows symbol#to_proc method to call private functions.
2
+ # Which can be useful if you want to have a class wrap itself in
3
+ # a Monad and call it private methods.
4
+
5
+ class Symbol
6
+ def to_proc
7
+ ->(v) { v.send(self) }
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'consequence/utils'
2
+
3
+ class Object
4
+ include Consequence::Utils
5
+ end
@@ -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
- proc.arity.abs == 1 ? [value] : [value, self]
41
+ [value, self][0, proc.arity.abs]
42
42
  end
43
43
 
44
44
  def wrap(value)
@@ -1,3 +1,5 @@
1
+ require 'consequence/monad'
2
+
1
3
  module Consequence
2
4
  class Something < Monad
3
5
  def >>(proc)
@@ -1,3 +1,5 @@
1
+ require 'consequence/monad'
2
+
1
3
  module Consequence
2
4
  class Success < Monad
3
5
  def >>(proc)
@@ -1,11 +1,11 @@
1
1
  module Consequence
2
- module Utils
3
- def send_to_value(*args)
4
- ->(v) { v.send(*args) }
5
- end
2
+ module Utils
3
+ def send_to_value(*args)
4
+ ->(v) { v.send(*args) }
5
+ end
6
6
 
7
- def send_to_monad(*args)
8
- ->(v, m) { m.send(*args) }
9
- end
10
- end
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.0
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-14 00:00:00.000000000 Z
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