microfsm 0.2.1 → 1.0.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 +11 -5
- data/examples/advanced.rb +7 -7
- data/examples/advanced.rb.bak +21 -0
- data/examples/basic.rb +4 -4
- data/examples/basic.rb.bak +26 -0
- data/examples/callbacks.rb +6 -5
- data/examples/callbacks.rb.bak +16 -0
- data/lib/microfsm/version.rb +2 -1
- data/lib/microfsm/version.rb.bak +2 -1
- data/lib/microfsm.rb +20 -8
- data/lib/microfsm.rb.bak +80 -0
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb5ea2d5710c8f5a3296cb1eeb0b8b56a18143faf35c55138e13d6abd3702cdc
|
|
4
|
+
data.tar.gz: 14cc5dfc48e7338d2d7bf5efb54499a24054b2aa89bafffd92f1f8026b091259
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 933ab09b4dcf57bcb0d3b229c4b125f3408c48f8759ef59cf9aea796e89cd775678bf452aa744c8f27e2768d8e10bab8cc889c3a21ab8153711238ff7a7e7f43
|
|
7
|
+
data.tar.gz: bff990c82be6edeffd463a1eefd34a0dd1b196b64a59ad93205edbbf15857162ea4b0b027bb8e14ec5c88092788c9996d00bcdf2c9beeeed88c0568cf4462602
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
MicroFSM implements a minimal/simple Finite-State Machine (FSM).
|
|
10
10
|
Transitions are triggered by events.
|
|
11
|
-
|
|
11
|
+
An action for a transition can be added as a callback.
|
|
12
12
|
|
|
13
13
|
Finite-State Machine are described elsewhere, e.g. Wikipedia.
|
|
14
14
|
|
|
@@ -68,15 +68,21 @@ fsm.state #=> :ignored
|
|
|
68
68
|
|
|
69
69
|
## Actions
|
|
70
70
|
|
|
71
|
-
Adding
|
|
71
|
+
Adding an action to a transition is trivial:
|
|
72
72
|
|
|
73
73
|
```ruby
|
|
74
|
-
fsm.when(:confirm, new: :confirmed) { |event|
|
|
75
|
-
|
|
74
|
+
fsm.when(:confirm, new: :confirmed) { |event, next_state|
|
|
75
|
+
count += 1
|
|
76
|
+
next_state # returning nil will disable the transition
|
|
77
|
+
}
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
## Version 1.*
|
|
79
81
|
|
|
82
|
+
*Actions* have been enhanced:
|
|
83
|
+
|
|
84
|
+
- next_state: a second parameter has been added
|
|
85
|
+
- a return value is expected (see example above)
|
|
80
86
|
|
|
81
87
|
## Miscellaneous
|
|
82
88
|
|
data/examples/advanced.rb
CHANGED
|
@@ -2,19 +2,19 @@ require "microfsm"
|
|
|
2
2
|
|
|
3
3
|
# This example can be run with ruby -I lib/ ./examples/advanced.rb
|
|
4
4
|
|
|
5
|
-
fsm = MicroFSM.new(:
|
|
6
|
-
proc = ->(event) { puts
|
|
7
|
-
fsm.when(:confirm,
|
|
8
|
-
.when(:ignore,
|
|
9
|
-
.when(:reset, confirmed: :
|
|
5
|
+
fsm = MicroFSM.new(:idle)
|
|
6
|
+
proc = ->(event, next_state) { puts next_state.capitalize; next_state }
|
|
7
|
+
fsm.when(:confirm, idle: :confirmed, &proc)
|
|
8
|
+
.when(:ignore, idle: :ignored, &proc)
|
|
9
|
+
.when(:reset, confirmed: :idle, ignored: :idle, &proc)
|
|
10
10
|
|
|
11
|
-
puts "Should print Confirmed,
|
|
11
|
+
puts "Should print Confirmed, Idle and Ignored:"
|
|
12
12
|
fsm.trigger(:confirm)
|
|
13
13
|
fsm.trigger(:ignore)
|
|
14
14
|
fsm.trigger(:reset)
|
|
15
15
|
fsm.trigger(:ignore)
|
|
16
16
|
|
|
17
|
-
puts "Should print all states: confirmed,
|
|
17
|
+
puts "Should print all states: confirmed, idle, ignored"
|
|
18
18
|
puts fsm.states.join ", "
|
|
19
19
|
|
|
20
20
|
puts "Should print all events: confirm, ignore, reset"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "microfsm"
|
|
2
|
+
|
|
3
|
+
# This example can be run with ruby -I lib/ ./examples/advanced.rb
|
|
4
|
+
|
|
5
|
+
fsm = MicroFSM.new(:idle)
|
|
6
|
+
proc = ->(event) { puts fsm.state.capitalize }
|
|
7
|
+
fsm.when(:confirm, idle: :confirmed, &proc)
|
|
8
|
+
.when(:ignore, idle: :ignored, &proc)
|
|
9
|
+
.when(:reset, confirmed: :idle, ignored: :idle, &proc)
|
|
10
|
+
|
|
11
|
+
puts "Should print Confirmed, Pending and Ignored:"
|
|
12
|
+
fsm.trigger(:confirm)
|
|
13
|
+
fsm.trigger(:ignore)
|
|
14
|
+
fsm.trigger(:reset)
|
|
15
|
+
fsm.trigger(:ignore)
|
|
16
|
+
|
|
17
|
+
puts "Should print all states: confirmed, ignored, idle
|
|
18
|
+
puts fsm.states.join ", "
|
|
19
|
+
|
|
20
|
+
puts "Should print all events: confirm, ignore, reset"
|
|
21
|
+
puts fsm.events.join ", "
|
data/examples/basic.rb
CHANGED
|
@@ -2,10 +2,10 @@ require "microfsm"
|
|
|
2
2
|
|
|
3
3
|
# This example can be run with ruby -I lib/ ./examples/basic.rb
|
|
4
4
|
|
|
5
|
-
fsm = MicroFSM.new(:
|
|
6
|
-
.when(:confirm,
|
|
7
|
-
.when(:ignore,
|
|
8
|
-
.when(:reset, confirmed: :
|
|
5
|
+
fsm = MicroFSM.new(:idle)
|
|
6
|
+
.when(:confirm, idle: :confirmed)
|
|
7
|
+
.when(:ignore, idle: :ignored)
|
|
8
|
+
.when(:reset, confirmed: :idle, ignored: :idle)
|
|
9
9
|
|
|
10
10
|
puts "Should print Confirmed, Reset and Ignored:"
|
|
11
11
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "microfsm"
|
|
2
|
+
|
|
3
|
+
# This example can be run with ruby -I lib/ ./examples/basic.rb
|
|
4
|
+
|
|
5
|
+
fsm = MicroFSM.new(:pending)
|
|
6
|
+
.when(:confirm, pending: :confirmed)
|
|
7
|
+
.when(:ignore, pending: :ignored)
|
|
8
|
+
.when(:reset, confirmed: :pending, ignored: :pending)
|
|
9
|
+
|
|
10
|
+
puts "Should print Confirmed, Reset and Ignored:"
|
|
11
|
+
|
|
12
|
+
if fsm.trigger(:confirm)
|
|
13
|
+
puts "Confirmed"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if fsm.trigger(:ignore)
|
|
17
|
+
puts "Ignored"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if fsm.trigger(:reset)
|
|
21
|
+
puts "Reset"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if fsm.trigger(:ignore)
|
|
25
|
+
puts "Ignored"
|
|
26
|
+
end
|
data/examples/callbacks.rb
CHANGED
|
@@ -2,12 +2,13 @@ require "microfsm"
|
|
|
2
2
|
|
|
3
3
|
# This example can be run with ruby -I lib/ ./examples/callbacks.rb
|
|
4
4
|
|
|
5
|
-
fsm = MicroFSM.new(:
|
|
6
|
-
.when(:confirm,
|
|
7
|
-
.when(:ignore,
|
|
8
|
-
.when(:reset, confirmed: :
|
|
5
|
+
fsm = MicroFSM.new(:idle)
|
|
6
|
+
.when(:confirm, idle: :confirmed) { |ev, ns| puts "Confirmed"; ns }
|
|
7
|
+
.when(:ignore, idle: :ignored) { |ev, ns| puts "Ignored"; ns }
|
|
8
|
+
.when(:reset, confirmed: :idle, ignored: :idle) do |ev, ns|
|
|
9
9
|
puts "Reset"
|
|
10
|
-
|
|
10
|
+
ns
|
|
11
|
+
end
|
|
11
12
|
|
|
12
13
|
puts "Should print Confirmed, Reset and Ignored:"
|
|
13
14
|
fsm.trigger(:confirm)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "microfsm"
|
|
2
|
+
|
|
3
|
+
# This example can be run with ruby -I lib/ ./examples/callbacks.rb
|
|
4
|
+
|
|
5
|
+
fsm = MicroFSM.new(:idle)
|
|
6
|
+
.when(:confirm, idle: :confirmed) { puts "Confirmed" }
|
|
7
|
+
.when(:ignore, idle: :ignored) { puts "Ignored" }
|
|
8
|
+
.when(:reset, confirmed: :idle, ignored: :idle) {
|
|
9
|
+
puts "Reset"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
puts "Should print Confirmed, Reset and Ignored:"
|
|
13
|
+
fsm.trigger(:confirm)
|
|
14
|
+
fsm.trigger(:ignore)
|
|
15
|
+
fsm.trigger(:reset)
|
|
16
|
+
fsm.trigger(:ignore)
|
data/lib/microfsm/version.rb
CHANGED
data/lib/microfsm/version.rb.bak
CHANGED
data/lib/microfsm.rb
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
|
+
require "ricecream"
|
|
2
|
+
|
|
1
3
|
class MicroFSM
|
|
2
4
|
InvalidEvent = Class.new(NoMethodError)
|
|
3
5
|
InvalidState = Class.new(ArgumentError)
|
|
4
6
|
InvalidTransition = Class.new(ArgumentError)
|
|
5
7
|
|
|
6
8
|
attr_accessor :state
|
|
9
|
+
attr_accessor :timed
|
|
10
|
+
attr_accessor :previous_utc
|
|
11
|
+
attr_accessor :current_utc
|
|
7
12
|
|
|
8
13
|
def initialize(initial_state)
|
|
9
14
|
@state = initial_state
|
|
15
|
+
@timed = false
|
|
10
16
|
@transitions_for = {}
|
|
11
|
-
@
|
|
17
|
+
@callback_for = {}
|
|
12
18
|
end
|
|
13
19
|
|
|
14
20
|
def when(event, transitions, &block)
|
|
15
21
|
@transitions_for[event] ||= {}
|
|
16
|
-
@
|
|
22
|
+
@callback_for[event] ||= {}
|
|
23
|
+
@timed = true if block
|
|
17
24
|
|
|
18
25
|
transitions.each do |from, to|
|
|
19
26
|
nto = @transitions_for[event][from]
|
|
20
27
|
raise InvalidTransition if nto && nto != to
|
|
21
28
|
|
|
22
29
|
@transitions_for[event][from] = to
|
|
23
|
-
@
|
|
24
|
-
@
|
|
30
|
+
@callback_for[event][from] = block if block
|
|
31
|
+
@current_utc = Time.now.utc if block
|
|
25
32
|
end
|
|
26
33
|
self
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
def trigger(event)
|
|
37
|
+
if @timed
|
|
38
|
+
@previous_utc = @current_utc
|
|
39
|
+
@current_utc = Time.now.utc
|
|
40
|
+
end
|
|
41
|
+
|
|
30
42
|
trigger?(event) and transit(event)
|
|
31
43
|
end
|
|
32
44
|
|
|
@@ -56,10 +68,10 @@ class MicroFSM
|
|
|
56
68
|
private
|
|
57
69
|
|
|
58
70
|
def transit(event)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
callback = @callback_for[event][@state]
|
|
72
|
+
next_state = @transitions_for[event][@state]
|
|
73
|
+
next_state = callback.call(event, next_state) if callback
|
|
74
|
+
@state = next_state if next_state
|
|
63
75
|
end
|
|
64
76
|
|
|
65
77
|
def msg(event)
|
data/lib/microfsm.rb.bak
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require "ricecream"
|
|
2
|
+
|
|
3
|
+
class MicroFSM
|
|
4
|
+
InvalidEvent = Class.new(NoMethodError)
|
|
5
|
+
InvalidState = Class.new(ArgumentError)
|
|
6
|
+
InvalidTransition = Class.new(ArgumentError)
|
|
7
|
+
|
|
8
|
+
attr_accessor :state
|
|
9
|
+
attr_accessor :timed
|
|
10
|
+
attr_accessor :previous_utc
|
|
11
|
+
attr_accessor :current_utc
|
|
12
|
+
|
|
13
|
+
def initialize(initial_state)
|
|
14
|
+
@state = initial_state
|
|
15
|
+
@timed = false
|
|
16
|
+
@transitions_for = {}
|
|
17
|
+
@callback_for = {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def when(event, transitions, &block)
|
|
21
|
+
@transitions_for[event] ||= {}
|
|
22
|
+
@callback_for[event] ||= {}
|
|
23
|
+
@timed = true if block
|
|
24
|
+
|
|
25
|
+
transitions.each do |from, to|
|
|
26
|
+
nto = @transitions_for[event][from]
|
|
27
|
+
raise InvalidTransition if nto && nto != to
|
|
28
|
+
|
|
29
|
+
@transitions_for[event][from] = to
|
|
30
|
+
@callback_for[event][from] ||= []
|
|
31
|
+
@callback_for[event][from] << block if block
|
|
32
|
+
end
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def trigger(event)
|
|
37
|
+
if @timed
|
|
38
|
+
@previous_utc = @current_utc
|
|
39
|
+
@current_utc = Time.now.utc
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
trigger?(event) and transit(event)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def trigger!(event)
|
|
46
|
+
trigger(event) or
|
|
47
|
+
raise InvalidState.new(msg(event))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def trigger?(event)
|
|
51
|
+
raise InvalidEvent.new(msg(event)) unless @transitions_for.has_key?(event)
|
|
52
|
+
|
|
53
|
+
@transitions_for[event].has_key?(state)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def events
|
|
57
|
+
@transitions_for.keys.sort
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def triggerable_events
|
|
61
|
+
events.select { |event| trigger?(event) }.sort
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def states
|
|
65
|
+
@transitions_for.values.map(&:to_a).flatten.uniq.sort
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def transit(event)
|
|
71
|
+
callback = @callback_for[event][@state]
|
|
72
|
+
@state = @transitions_for[event][@state]
|
|
73
|
+
callback.each { |callback| callback.call(event) }
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def msg(event)
|
|
78
|
+
"State: #{@state}; Event: #{event}"
|
|
79
|
+
end
|
|
80
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: microfsm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dittmar Krall
|
|
@@ -38,7 +38,7 @@ dependencies:
|
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '0'
|
|
40
40
|
description: MicroFSM implements a minimal/simple Finite-State Machine (FSM). Transitions
|
|
41
|
-
are triggered by events.
|
|
41
|
+
are triggered by events. An action for a transition can be added as a callback.
|
|
42
42
|
email: dittmar.krall@matiq.com
|
|
43
43
|
executables: []
|
|
44
44
|
extensions: []
|
|
@@ -49,9 +49,13 @@ files:
|
|
|
49
49
|
- MIT-LICENSE
|
|
50
50
|
- README.md
|
|
51
51
|
- examples/advanced.rb
|
|
52
|
+
- examples/advanced.rb.bak
|
|
52
53
|
- examples/basic.rb
|
|
54
|
+
- examples/basic.rb.bak
|
|
53
55
|
- examples/callbacks.rb
|
|
56
|
+
- examples/callbacks.rb.bak
|
|
54
57
|
- lib/microfsm.rb
|
|
58
|
+
- lib/microfsm.rb.bak
|
|
55
59
|
- lib/microfsm/version.rb
|
|
56
60
|
- lib/microfsm/version.rb.bak
|
|
57
61
|
homepage: https://github.com/matique/microfsm
|
|
@@ -72,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
72
76
|
- !ruby/object:Gem::Version
|
|
73
77
|
version: '0'
|
|
74
78
|
requirements: []
|
|
75
|
-
rubygems_version: 4.0.
|
|
79
|
+
rubygems_version: 4.0.10
|
|
76
80
|
specification_version: 4
|
|
77
81
|
summary: Minimal Finite State Machine.
|
|
78
82
|
test_files: []
|