stateful_enum 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -9
- data/lib/stateful_enum/machine.rb +31 -6
- data/lib/stateful_enum/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffeec178154391f427428dcb96dfe904071069a8
|
4
|
+
data.tar.gz: 9928fb31c685db67d2a9d70d232b0d9736fa88ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9330b01347ddc68584bd6b87417e22d0577eb6f15e4a902c40af48b5a60b408977ff799df33280eed09800421004b1c3e9bffe264d00b017f38a5545f22352cb
|
7
|
+
data.tar.gz: 9bad2968b578fcf1141fb78c1b69284a6750c64596a68056ff733173aba2492f58842ff6005bffd79ee435d7140f079e44e2ee0e52b814a065ce64e187f337d3
|
data/README.md
CHANGED
@@ -41,13 +41,26 @@ The stateful_enum gem extends AR::Enum definition to take a block with a similar
|
|
41
41
|
Example:
|
42
42
|
```ruby
|
43
43
|
class Bug < ApplicationRecord
|
44
|
-
enum status: {unassigned: 0, assigned: 1, resolved: 2} do
|
44
|
+
enum status: {unassigned: 0, assigned: 1, resolved: 2, closed: 3} do
|
45
45
|
event :assign do
|
46
46
|
transition :unassigned => :assigned
|
47
47
|
end
|
48
|
+
|
48
49
|
event :resolve do
|
50
|
+
before do
|
51
|
+
self.resolved_at = Time.zone.now
|
52
|
+
end
|
53
|
+
|
49
54
|
transition [:unassigned, :assigned] => :resolved
|
50
55
|
end
|
56
|
+
|
57
|
+
event :close do
|
58
|
+
after do
|
59
|
+
Notifier.notify "Bug##{id} has been closed."
|
60
|
+
end
|
61
|
+
|
62
|
+
transition all - [:closed] => :closed
|
63
|
+
end
|
51
64
|
end
|
52
65
|
end
|
53
66
|
```
|
@@ -91,22 +104,27 @@ There are a few important details to note regarding this feature:
|
|
91
104
|
* The `transition` method takes a Hash each key of which is state "from" transitions to the Hash value.
|
92
105
|
* The "from" states and the "to" states should both be given in Symbols.
|
93
106
|
* The "from" state can be multiple states, in which case the key can be given as an Array of states, as shown in the usage example.
|
107
|
+
* The "from" state can be `all` that means all defined states.
|
94
108
|
|
95
|
-
###
|
109
|
+
### :if and :unless Condition
|
96
110
|
|
97
|
-
|
111
|
+
The `transition` method takes an `:if` or `:unless` option as a Proc.
|
98
112
|
|
99
|
-
|
113
|
+
Example:
|
114
|
+
```ruby
|
115
|
+
event :assign do
|
116
|
+
transition :unassigned => :assigned, if: -> { !!assigned_to }
|
117
|
+
end
|
118
|
+
```
|
100
119
|
|
101
|
-
|
120
|
+
### Event hooks
|
102
121
|
|
103
|
-
|
122
|
+
You can define `before` and `after` event hooks inside of an `event` block.
|
104
123
|
|
105
|
-
**TODO**
|
106
124
|
|
107
|
-
|
125
|
+
## TODO
|
108
126
|
|
109
|
-
|
127
|
+
* Better Error handling
|
110
128
|
|
111
129
|
|
112
130
|
## Contributing
|
@@ -27,11 +27,17 @@ module StatefulEnum
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def define_transition_methods
|
30
|
-
column, name, transitions = @column, @name, @transitions
|
30
|
+
column, name, transitions, before, after = @column, @name, @transitions, @before, @after
|
31
31
|
|
32
32
|
@model.send(:define_method, name) do
|
33
|
-
|
34
|
-
|
33
|
+
to, condition = transitions[self.send(column).to_sym]
|
34
|
+
#TODO better error
|
35
|
+
if to && (!condition || instance_exec(&condition))
|
36
|
+
#TODO transaction?
|
37
|
+
instance_eval(&before) if before
|
38
|
+
ret = self.class.instance_variable_get(:@_enum_methods_module).instance_method("#{to}!").bind(self).call
|
39
|
+
instance_eval(&after) if after
|
40
|
+
ret
|
35
41
|
else
|
36
42
|
false
|
37
43
|
end
|
@@ -46,19 +52,38 @@ module StatefulEnum
|
|
46
52
|
end
|
47
53
|
|
48
54
|
@model.send(:define_method, "#{name}_transition") do
|
49
|
-
transitions[self.send(column).to_sym]
|
55
|
+
transitions[self.send(column).to_sym].try! :first
|
50
56
|
end
|
51
57
|
end
|
52
58
|
|
53
|
-
def transition(transitions)
|
59
|
+
def transition(transitions, options = {})
|
60
|
+
if options.blank?
|
61
|
+
options[:if] = transitions.delete :if
|
62
|
+
#TODO should err if if & unless were specified together?
|
63
|
+
if (unless_condition = transitions.delete :unless)
|
64
|
+
options[:if] = -> { !instance_exec(&unless_condition) }
|
65
|
+
end
|
66
|
+
end
|
54
67
|
transitions.each_pair do |from, to|
|
55
68
|
raise "Undefined state #{to}" unless @states.has_key? to
|
56
69
|
Array(from).each do |f|
|
57
70
|
raise "Undefined state #{f}" unless @states.has_key? f
|
58
|
-
@transitions[f] = to
|
71
|
+
@transitions[f] = [to, options[:if]]
|
59
72
|
end
|
60
73
|
end
|
61
74
|
end
|
75
|
+
|
76
|
+
def all
|
77
|
+
@states.keys
|
78
|
+
end
|
79
|
+
|
80
|
+
def before(&block)
|
81
|
+
@before = block
|
82
|
+
end
|
83
|
+
|
84
|
+
def after(&block)
|
85
|
+
@after = block
|
86
|
+
end
|
62
87
|
end
|
63
88
|
end
|
64
89
|
end
|