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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7974725af299cb54f56eb1542a52799c2b7530d5e389c66eec09c8a4c02de1b
4
- data.tar.gz: a5651e39934546af36c5764f8fab0ba5703e7aac59ffc8d11c84564c066c087b
3
+ metadata.gz: eb5ea2d5710c8f5a3296cb1eeb0b8b56a18143faf35c55138e13d6abd3702cdc
4
+ data.tar.gz: 14cc5dfc48e7338d2d7bf5efb54499a24054b2aa89bafffd92f1f8026b091259
5
5
  SHA512:
6
- metadata.gz: 5338e4e3b5f018c149c8941199f971722ff382222b8fb5b4032f629fb2687b7caf1eda320d3484b5aa1766c644a918caa994aa72b528c4ea54acd97ed8747135
7
- data.tar.gz: a89939784e83be8223b391703301167e3f9b4f1098e5a2132837d5c9f93e7b517c1fa88591d165aded7ae0533ce40039b3f4a26ac6fc2f88e9ea59c0399732ab
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
- Actions for a transition can be added as callbacks.
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 actions to a transition is trivial:
71
+ Adding an action to a transition is trivial:
72
72
 
73
73
  ```ruby
74
- fsm.when(:confirm, new: :confirmed) { |event| count += 1 }
75
- fsm.when(:confirm, new: :confirmed) { |event| foo(event) }
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
- Two actions/callbacks are triggered in the previous example.
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(:pending)
6
- proc = ->(event) { puts fsm.state.capitalize }
7
- fsm.when(:confirm, pending: :confirmed, &proc)
8
- .when(:ignore, pending: :ignored, &proc)
9
- .when(:reset, confirmed: :pending, ignored: :pending, &proc)
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, Pending and Ignored:"
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, ignored, pending"
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(:pending)
6
- .when(:confirm, pending: :confirmed)
7
- .when(:ignore, pending: :ignored)
8
- .when(:reset, confirmed: :pending, ignored: :pending)
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
@@ -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(:pending)
6
- .when(:confirm, pending: :confirmed) { puts "Confirmed" }
7
- .when(:ignore, pending: :ignored) { puts "Ignored" }
8
- .when(:reset, confirmed: :pending, ignored: :pending) {
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)
@@ -1,5 +1,6 @@
1
1
  class MicroFSM
2
- VERSION = "0.2.1" # 2026-03-31
2
+ VERSION = "1.0.0" # 2026-04-20
3
+ # VERSION = "0.2.1" # 2026-03-31
3
4
  # VERSION = "0.2.0" # 2026-01-01
4
5
  # VERSION = "0.1.11" # 2025-06-19
5
6
  # VERSION = "0.1.10" # 2024-10-20
@@ -1,5 +1,6 @@
1
1
  class MicroFSM
2
- VERSION = "0.2.0" # 2026-01-01
2
+ VERSION = "0.2.1" # 2026-03-31
3
+ # VERSION = "0.2.0" # 2026-01-01
3
4
  # VERSION = "0.1.11" # 2025-06-19
4
5
  # VERSION = "0.1.10" # 2024-10-20
5
6
  # VERSION = "0.1.9" # 2024-05-22
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
- @callbacks_for = {}
17
+ @callback_for = {}
12
18
  end
13
19
 
14
20
  def when(event, transitions, &block)
15
21
  @transitions_for[event] ||= {}
16
- @callbacks_for[event] ||= {}
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
- @callbacks_for[event][from] ||= []
24
- @callbacks_for[event][from] << block if block
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
- callbacks = @callbacks_for[event][@state]
60
- @state = @transitions_for[event][@state]
61
- callbacks.each { |callback| callback.call(event) }
62
- true
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)
@@ -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.2.1
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. Actions for a transition can be added as callbacks.
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.6
79
+ rubygems_version: 4.0.10
76
80
  specification_version: 4
77
81
  summary: Minimal Finite State Machine.
78
82
  test_files: []