stateful_enum 0.1.0 → 0.2.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 +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
|