stateful_enum 0.5.0 → 0.6.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/.travis.yml +3 -0
- data/README.md +32 -0
- data/gemfiles/Gemfile-rails.6.0.x +6 -0
- data/lib/generators/stateful_enum/plantuml_generator.rb +1 -2
- data/lib/stateful_enum/active_record_extension.rb +2 -2
- data/lib/stateful_enum/machine.rb +21 -18
- data/lib/stateful_enum/railtie.rb +6 -2
- data/lib/stateful_enum/state_inspection.rb +44 -0
- data/lib/stateful_enum/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d0d82f2cf13496a059030aac0a34a998e47997bcbf6605637fa488c5363454d
|
4
|
+
data.tar.gz: 69fc206ccfc3d4290ad0961cac0d011e92ed1fa5421c0064bd881213d52082d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3f5cec3415b7401c36acf28d5dda810d75818cc88b38a768e721757aaf508714ee0613b7926bb0b5e05832df83e6d7deadc3cc0b816eb3e7ab9a6286f6b1399
|
7
|
+
data.tar.gz: 6a8d8196552d59c696c42872ae3a9decb62ddef4e75b42566af8e45cd2d3887e3fe6688808ac230f3d35ba7501f4e06328a4fad93462d3e8aee4fca985da4720
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -122,6 +122,38 @@ end
|
|
122
122
|
|
123
123
|
You can define `before` and `after` event hooks inside of an `event` block.
|
124
124
|
|
125
|
+
### Inspecting All Defined Events And Current Possible Events
|
126
|
+
|
127
|
+
You can get the list of defined events from the model class:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Bug.stateful_enum.events
|
131
|
+
#=> an Array of all defined StatefulEnum::Machine::Event objects
|
132
|
+
```
|
133
|
+
|
134
|
+
And you can get the list of possible event definitions from the model instance:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
Bug.new(status: :assigned).stateful_enum.possible_events
|
138
|
+
#=> an Array of StatefulEnum::Machine::Event objects that are callable from the receiver object
|
139
|
+
```
|
140
|
+
|
141
|
+
Maybe what you really need for your app is the list of possible event "names":
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
Bug.new(status: :assigned).stateful_enum.possible_event_names
|
145
|
+
#=> [:resolve, :close]
|
146
|
+
```
|
147
|
+
|
148
|
+
You can get the list of next possible state names as well:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
Bug.new(status: :assigned).stateful_enum.possible_states
|
152
|
+
#=> [:resolved, :closed]
|
153
|
+
```
|
154
|
+
|
155
|
+
These features would help some kind of metaprogramming over state transitions.
|
156
|
+
|
125
157
|
|
126
158
|
## Generating State Machine Diagrams
|
127
159
|
|
@@ -10,13 +10,13 @@ module StatefulEnum
|
|
10
10
|
# end
|
11
11
|
# end
|
12
12
|
def enum(definitions, &block)
|
13
|
-
prefix, suffix = definitions[:_prefix], definitions[:_suffix] if Rails::VERSION::
|
13
|
+
prefix, suffix = definitions[:_prefix], definitions[:_suffix] if Rails::VERSION::MAJOR >= 5
|
14
14
|
enum = super definitions
|
15
15
|
|
16
16
|
if block
|
17
17
|
definitions.each_key do |column|
|
18
18
|
states = enum[column]
|
19
|
-
StatefulEnum::Machine.new
|
19
|
+
(@_defined_stateful_enums ||= []) << StatefulEnum::Machine.new(self, column, (states.is_a?(Hash) ? states.keys : states), prefix, suffix, &block)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module StatefulEnum
|
4
4
|
class Machine
|
5
|
+
attr_reader :events
|
6
|
+
|
5
7
|
def initialize(model, column, states, prefix, suffix, &block)
|
6
|
-
@model, @column, @states, @
|
8
|
+
@model, @column, @states, @events = model, column, states, []
|
7
9
|
@prefix = if prefix
|
8
10
|
prefix == true ? "#{column}_" : "#{prefix}_"
|
9
11
|
end
|
@@ -20,40 +22,41 @@ module StatefulEnum
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def event(name, &block)
|
23
|
-
raise ArgumentError, "event: :#{name} has already been defined." if @
|
24
|
-
Event.new
|
25
|
-
@event_names << name
|
25
|
+
raise ArgumentError, "event: :#{name} has already been defined." if @events.map(&:name).include? name
|
26
|
+
@events << Event.new(@model, @column, @states, @prefix, @suffix, name, &block)
|
26
27
|
end
|
27
28
|
|
28
29
|
class Event
|
30
|
+
attr_reader :name, :value_method_name
|
31
|
+
|
29
32
|
def initialize(model, column, states, prefix, suffix, name, &block)
|
30
33
|
@states, @name, @transitions, @before, @after = states, name, {}, [], []
|
31
34
|
|
32
35
|
instance_eval(&block) if block
|
33
36
|
|
34
37
|
transitions, before, after = @transitions, @before, @after
|
35
|
-
|
38
|
+
@value_method_name = value_method_name = :"#{prefix}#{name}#{suffix}"
|
36
39
|
|
37
40
|
# defining event methods
|
38
41
|
model.class_eval do
|
39
42
|
# def assign()
|
40
|
-
detect_enum_conflict! column,
|
43
|
+
detect_enum_conflict! column, value_method_name
|
41
44
|
|
42
45
|
# defining callbacks
|
43
|
-
define_callbacks
|
46
|
+
define_callbacks value_method_name
|
44
47
|
before.each do |before_callback|
|
45
|
-
model.set_callback
|
48
|
+
model.set_callback value_method_name, :before, before_callback
|
46
49
|
end
|
47
50
|
after.each do |after_callback|
|
48
|
-
model.set_callback
|
51
|
+
model.set_callback value_method_name, :after, after_callback
|
49
52
|
end
|
50
53
|
|
51
|
-
define_method
|
54
|
+
define_method value_method_name do
|
52
55
|
to, condition = transitions[send(column).to_sym]
|
53
56
|
#TODO better error
|
54
57
|
if to && (!condition || instance_exec(&condition))
|
55
58
|
#TODO transaction?
|
56
|
-
run_callbacks
|
59
|
+
run_callbacks value_method_name do
|
57
60
|
original_method = self.class.send(:_enum_methods_module).instance_method "#{prefix}#{to}#{suffix}!"
|
58
61
|
original_method.bind(self).call
|
59
62
|
end
|
@@ -63,14 +66,14 @@ module StatefulEnum
|
|
63
66
|
end
|
64
67
|
|
65
68
|
# def assign!()
|
66
|
-
detect_enum_conflict! column, "#{
|
67
|
-
define_method "#{
|
68
|
-
send(
|
69
|
+
detect_enum_conflict! column, "#{value_method_name}!"
|
70
|
+
define_method "#{value_method_name}!" do
|
71
|
+
send(value_method_name) || raise('Invalid transition')
|
69
72
|
end
|
70
73
|
|
71
74
|
# def can_assign?()
|
72
|
-
detect_enum_conflict! column, "can_#{
|
73
|
-
define_method "can_#{
|
75
|
+
detect_enum_conflict! column, "can_#{value_method_name}?"
|
76
|
+
define_method "can_#{value_method_name}?" do
|
74
77
|
state = send(column).to_sym
|
75
78
|
return false unless transitions.key? state
|
76
79
|
_to, condition = transitions[state]
|
@@ -78,8 +81,8 @@ module StatefulEnum
|
|
78
81
|
end
|
79
82
|
|
80
83
|
# def assign_transition()
|
81
|
-
detect_enum_conflict! column, "#{
|
82
|
-
define_method "#{
|
84
|
+
detect_enum_conflict! column, "#{value_method_name}_transition"
|
85
|
+
define_method "#{value_method_name}_transition" do
|
83
86
|
transitions[send(column).to_sym].try! :first
|
84
87
|
end
|
85
88
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'stateful_enum/active_record_extension'
|
4
|
+
require 'stateful_enum/state_inspection'
|
4
5
|
|
5
6
|
module StatefulEnum
|
6
7
|
class Railtie < ::Rails::Railtie
|
7
|
-
|
8
|
-
|
8
|
+
initializer 'stateful_enum' do
|
9
|
+
ActiveSupport.on_load :active_record do
|
10
|
+
::ActiveRecord::Base.extend StatefulEnum::ActiveRecordEnumExtension
|
11
|
+
::ActiveRecord::Base.include StatefulEnum::StateInspection
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stateful_enum/machine'
|
4
|
+
|
5
|
+
module StatefulEnum
|
6
|
+
module StateInspection
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def stateful_enum
|
11
|
+
@_defined_stateful_enums
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def stateful_enum
|
16
|
+
StateInspector.new(self.class.stateful_enum, self)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class StateInspector
|
21
|
+
def initialize(defined_stateful_enums, model_instance)
|
22
|
+
@defined_stateful_enums, @model_instance = defined_stateful_enums, model_instance
|
23
|
+
end
|
24
|
+
|
25
|
+
# List of possible events from the current state
|
26
|
+
def possible_events
|
27
|
+
@defined_stateful_enums.flat_map {|se| se.events.select {|e| @model_instance.send("can_#{e.value_method_name}?") } }
|
28
|
+
end
|
29
|
+
|
30
|
+
# List of possible event names from the current state
|
31
|
+
def possible_event_names
|
32
|
+
possible_events.map(&:value_method_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
# List of transitionable states from the current state
|
36
|
+
def possible_states
|
37
|
+
@defined_stateful_enums.flat_map do |stateful_enum|
|
38
|
+
col = stateful_enum.instance_variable_get :@column
|
39
|
+
pe = stateful_enum.events.select {|e| @model_instance.send("can_#{e.value_method_name}?") }
|
40
|
+
pe.flat_map {|e| e.instance_variable_get(:@transitions)[@model_instance.send(col).to_sym].first }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stateful_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akira Matsuda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- gemfiles/Gemfile-rails.5.0.x
|
115
115
|
- gemfiles/Gemfile-rails.5.1.x
|
116
116
|
- gemfiles/Gemfile-rails.5.2.x
|
117
|
+
- gemfiles/Gemfile-rails.6.0.x
|
117
118
|
- gemfiles/Gemfile-rails.edge
|
118
119
|
- lib/generators/stateful_enum/graph_generator.rb
|
119
120
|
- lib/generators/stateful_enum/plantuml_generator.rb
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- lib/stateful_enum/active_record_extension.rb
|
122
123
|
- lib/stateful_enum/machine.rb
|
123
124
|
- lib/stateful_enum/railtie.rb
|
125
|
+
- lib/stateful_enum/state_inspection.rb
|
124
126
|
- lib/stateful_enum/version.rb
|
125
127
|
- stateful_enum.gemspec
|
126
128
|
homepage: https://github.com/amatsuda/stateful_enum
|
@@ -142,8 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
144
|
- !ruby/object:Gem::Version
|
143
145
|
version: '0'
|
144
146
|
requirements: []
|
145
|
-
|
146
|
-
rubygems_version: 2.7.8
|
147
|
+
rubygems_version: 3.0.3
|
147
148
|
signing_key:
|
148
149
|
specification_version: 4
|
149
150
|
summary: A state machine plugin on top of ActiveRecord::Enum
|