finite_machine 0.7.0 → 0.7.1
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 +2 -2
- data/CHANGELOG.md +5 -0
- data/README.md +2 -2
- data/lib/finite_machine.rb +13 -1
- data/lib/finite_machine/dsl.rb +11 -6
- data/lib/finite_machine/safety.rb +32 -5
- data/lib/finite_machine/state_machine.rb +2 -1
- data/lib/finite_machine/version.rb +1 -1
- data/spec/unit/async_events_spec.rb +3 -2
- data/spec/unit/callbacks_spec.rb +79 -3
- data/spec/unit/define_spec.rb +1 -1
- data/spec/unit/initialize_spec.rb +5 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d0521fc82d97ac5139abe2fcea0ed72532af05fe
|
|
4
|
+
data.tar.gz: 260b8c31a86e2c3f80018aad2640c62222cea2af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f443039daa14568b5bc2424d6346b89da989494bde20c416e6c7186d1692dd878a1a1bae3e9dcd9a6271c4bfa2bed42d7c795b24c53883a692ffc672a9ec05bc
|
|
7
|
+
data.tar.gz: 4cc03728f4c4694f3ebac12bb3f112622b84f877efcbea2ef0f783a0005ee93d889b9317922e09e87f2f5a0ddc189d5618baa17bf498024c8263d783f1e77e83
|
data/.travis.yml
CHANGED
|
@@ -12,13 +12,13 @@ matrix:
|
|
|
12
12
|
- rvm: jruby-20mode
|
|
13
13
|
- rvm: jruby-21mode
|
|
14
14
|
- rvm: jruby-head
|
|
15
|
-
- rvm: rbx
|
|
15
|
+
- rvm: rbx-2
|
|
16
16
|
allow_failures:
|
|
17
17
|
- rvm: ruby-head
|
|
18
18
|
- rvm: jruby-head
|
|
19
19
|
- rvm: jruby-20mode
|
|
20
20
|
- rvm: jruby-21mode
|
|
21
|
-
- rvm: rbx
|
|
21
|
+
- rvm: rbx-2
|
|
22
22
|
fast_finish: true
|
|
23
23
|
branches:
|
|
24
24
|
only: master
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
[][travis]
|
|
4
4
|
[][codeclimate]
|
|
5
5
|
[][coverage]
|
|
6
|
-
[][inchpages]
|
|
7
7
|
|
|
8
8
|
[gem]: http://badge.fury.io/rb/finite_machine
|
|
9
9
|
[travis]: http://travis-ci.org/peter-murach/finite_machine
|
|
10
10
|
[codeclimate]: https://codeclimate.com/github/peter-murach/finite_machine
|
|
11
11
|
[coverage]: https://coveralls.io/r/peter-murach/finite_machine
|
|
12
|
-
[inchpages]: http://inch-
|
|
12
|
+
[inchpages]: http://inch-ci.org/github/peter-murach/finite_machine
|
|
13
13
|
|
|
14
14
|
A minimal finite state machine with a straightforward and intuitive syntax. You can quickly model states and add callbacks that can be triggered synchronously or asynchronously. The machine is event driven with a focus on passing synchronous and asynchronous messages to trigger state transitions.
|
|
15
15
|
|
data/lib/finite_machine.rb
CHANGED
|
@@ -27,13 +27,16 @@ require "finite_machine/observer"
|
|
|
27
27
|
require "finite_machine/listener"
|
|
28
28
|
|
|
29
29
|
module FiniteMachine
|
|
30
|
-
|
|
30
|
+
# Default state name
|
|
31
31
|
DEFAULT_STATE = :none
|
|
32
32
|
|
|
33
|
+
# Initial default event name
|
|
33
34
|
DEFAULT_EVENT_NAME = :init
|
|
34
35
|
|
|
36
|
+
# Describe any state transition
|
|
35
37
|
ANY_STATE = :any
|
|
36
38
|
|
|
39
|
+
# Describe any event name
|
|
37
40
|
ANY_EVENT = :any
|
|
38
41
|
|
|
39
42
|
# Returned when transition has successfully performed
|
|
@@ -75,6 +78,15 @@ module FiniteMachine
|
|
|
75
78
|
|
|
76
79
|
# TODO: this should instantiate system not the state machine
|
|
77
80
|
# and then delegate calls to StateMachine instance etc...
|
|
81
|
+
#
|
|
82
|
+
# @example
|
|
83
|
+
# FiniteMachine.define do
|
|
84
|
+
# ...
|
|
85
|
+
# end
|
|
86
|
+
#
|
|
87
|
+
# @return [FiniteMachine::StateMachine]
|
|
88
|
+
#
|
|
89
|
+
# @api public
|
|
78
90
|
def define(*args, &block)
|
|
79
91
|
StateMachine.new(*args, &block)
|
|
80
92
|
end
|
data/lib/finite_machine/dsl.rb
CHANGED
|
@@ -68,12 +68,17 @@ module FiniteMachine
|
|
|
68
68
|
# @api public
|
|
69
69
|
def initial(value)
|
|
70
70
|
state, name, self.defer = parse(value)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
self.initial_event = name
|
|
72
|
+
machine.event(name, from: FiniteMachine::DEFAULT_STATE, to: state)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Trigger initial event
|
|
76
|
+
#
|
|
77
|
+
# @return [nil]
|
|
78
|
+
#
|
|
79
|
+
# @api private
|
|
80
|
+
def trigger_init
|
|
81
|
+
machine.send(:"#{initial_event}") unless defer
|
|
77
82
|
end
|
|
78
83
|
|
|
79
84
|
# Attach state machine to an object
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
module FiniteMachine
|
|
4
4
|
# Module for responsible for safety checks against known methods
|
|
5
5
|
module Safety
|
|
6
|
-
|
|
7
6
|
EVENT_CONFLICT_MESSAGE = \
|
|
8
7
|
"You tried to define an event named \"%{name}\", however this would " \
|
|
9
8
|
"generate \"%{type}\" method \"%{method}\", which is already defined " \
|
|
@@ -54,14 +53,12 @@ module FiniteMachine
|
|
|
54
53
|
#
|
|
55
54
|
# @api public
|
|
56
55
|
def ensure_valid_callback_name!(event_type, name)
|
|
57
|
-
message = if
|
|
58
|
-
event_type < HookEvent::Anyaction
|
|
56
|
+
message = if wrong_event_name?(name, event_type)
|
|
59
57
|
EVENT_CALLBACK_CONFLICT_MESSAGE % {
|
|
60
58
|
type: "on_#{event_type.to_s}",
|
|
61
59
|
name: name
|
|
62
60
|
}
|
|
63
|
-
elsif
|
|
64
|
-
event_type < HookEvent::Anystate
|
|
61
|
+
elsif wrong_state_name?(name, event_type)
|
|
65
62
|
STATE_CALLBACK_CONFLICT_MESSAGE % {
|
|
66
63
|
type: "on_#{event_type.to_s}",
|
|
67
64
|
name: name
|
|
@@ -79,6 +76,36 @@ module FiniteMachine
|
|
|
79
76
|
|
|
80
77
|
private
|
|
81
78
|
|
|
79
|
+
# Check if event name exists
|
|
80
|
+
#
|
|
81
|
+
# @param [Symbol] name
|
|
82
|
+
#
|
|
83
|
+
# @param [FiniteMachine::HookEvent] event_type
|
|
84
|
+
#
|
|
85
|
+
# @return [Boolean]
|
|
86
|
+
#
|
|
87
|
+
# @api private
|
|
88
|
+
def wrong_event_name?(name, event_type)
|
|
89
|
+
machine.states.include?(name) &&
|
|
90
|
+
!machine.event_names.include?(name) &&
|
|
91
|
+
event_type < HookEvent::Anyaction
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Check if state name exists
|
|
95
|
+
#
|
|
96
|
+
# @param [Symbol] name
|
|
97
|
+
#
|
|
98
|
+
# @param [FiniteMachine::HookEvent] event_type
|
|
99
|
+
#
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
def wrong_state_name?(name, event_type)
|
|
104
|
+
machine.event_names.include?(name) &&
|
|
105
|
+
!machine.states.include?(name) &&
|
|
106
|
+
event_type < HookEvent::Anystate
|
|
107
|
+
end
|
|
108
|
+
|
|
82
109
|
def fail_invalid_callback_error(message)
|
|
83
110
|
exception = InvalidCallbackNameError
|
|
84
111
|
machine.catch_error(exception) || fail(exception, message)
|
|
@@ -43,7 +43,7 @@ module FiniteMachine
|
|
|
43
43
|
# The state machine event definitions
|
|
44
44
|
attr_threadsafe :events_chain
|
|
45
45
|
|
|
46
|
-
def_delegators :@dsl, :initial, :terminal, :target
|
|
46
|
+
def_delegators :@dsl, :initial, :terminal, :target, :trigger_init
|
|
47
47
|
|
|
48
48
|
def_delegator :@events_dsl, :event
|
|
49
49
|
|
|
@@ -63,6 +63,7 @@ module FiniteMachine
|
|
|
63
63
|
@dsl = DSL.new(self, attributes)
|
|
64
64
|
|
|
65
65
|
@dsl.call(&block) if block_given?
|
|
66
|
+
trigger_init
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
# @example
|
data/spec/unit/callbacks_spec.rb
CHANGED
|
@@ -98,6 +98,17 @@ describe FiniteMachine, 'callbacks' do
|
|
|
98
98
|
}
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
+
expect(fsm.current).to eq(:green)
|
|
102
|
+
expect(called).to eq([
|
|
103
|
+
'on_before',
|
|
104
|
+
'on_exit',
|
|
105
|
+
'on_transition_green',
|
|
106
|
+
'on_transition',
|
|
107
|
+
'on_enter_green',
|
|
108
|
+
'on_enter',
|
|
109
|
+
'on_after'
|
|
110
|
+
])
|
|
111
|
+
|
|
101
112
|
called = []
|
|
102
113
|
fsm.slow
|
|
103
114
|
expect(called).to eql([
|
|
@@ -179,6 +190,11 @@ describe FiniteMachine, 'callbacks' do
|
|
|
179
190
|
expect(fsm.current).to eq(:previous)
|
|
180
191
|
fsm.go
|
|
181
192
|
expect(called).to eq([
|
|
193
|
+
'before_init',
|
|
194
|
+
'exit_none',
|
|
195
|
+
'transition_none_previous',
|
|
196
|
+
'enter_previous',
|
|
197
|
+
'after_init',
|
|
182
198
|
'before_go',
|
|
183
199
|
'guard',
|
|
184
200
|
'exit_previous',
|
|
@@ -226,6 +242,14 @@ describe FiniteMachine, 'callbacks' do
|
|
|
226
242
|
}
|
|
227
243
|
end
|
|
228
244
|
|
|
245
|
+
expect(fsm.current).to eql(:green)
|
|
246
|
+
expect(called).to eql([
|
|
247
|
+
'on_before',
|
|
248
|
+
'on_exit',
|
|
249
|
+
'on_transition',
|
|
250
|
+
'on_enter',
|
|
251
|
+
'on_after'
|
|
252
|
+
])
|
|
229
253
|
called = []
|
|
230
254
|
fsm.slow
|
|
231
255
|
expect(fsm.current).to eql(:yellow)
|
|
@@ -539,14 +563,16 @@ describe FiniteMachine, 'callbacks' do
|
|
|
539
563
|
|
|
540
564
|
once_on_transition_green do |event| called << 'once_on_transition_green' end
|
|
541
565
|
once_on_transition_yellow do |event| called << 'once_on_transition_yellow' end
|
|
542
|
-
|
|
566
|
+
once_on_exit_none do |event| called << 'once_on_exit_none' end
|
|
543
567
|
once_on_exit_green do |event| called << 'once_on_exit_green' end
|
|
544
568
|
once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
|
|
545
569
|
|
|
546
570
|
# event callbacks
|
|
571
|
+
once_on_before_init do |event| called << 'once_on_before_init' end
|
|
547
572
|
once_on_before_slow do |event| called << 'once_on_before_slow' end
|
|
548
573
|
once_on_before_go do |event| called << 'once_on_before_go' end
|
|
549
574
|
|
|
575
|
+
once_on_after_init do |event| called << 'once_on_after_init' end
|
|
550
576
|
once_on_after_slow do |event| called << 'once_on_after_slow' end
|
|
551
577
|
once_on_after_go do |event| called << 'once_on_after_go' end
|
|
552
578
|
}
|
|
@@ -559,6 +585,11 @@ describe FiniteMachine, 'callbacks' do
|
|
|
559
585
|
fsm.slow
|
|
560
586
|
expect(fsm.current).to eql(:yellow)
|
|
561
587
|
expect(called).to eql([
|
|
588
|
+
'once_on_before_init',
|
|
589
|
+
'once_on_exit_none',
|
|
590
|
+
'once_on_transition_green',
|
|
591
|
+
'once_on_enter_green',
|
|
592
|
+
'once_on_after_init',
|
|
562
593
|
'once_on_before_slow',
|
|
563
594
|
'once_on_exit_green',
|
|
564
595
|
'once_on_transition_yellow',
|
|
@@ -566,8 +597,6 @@ describe FiniteMachine, 'callbacks' do
|
|
|
566
597
|
'once_on_after_slow',
|
|
567
598
|
'once_on_before_go',
|
|
568
599
|
'once_on_exit_yellow',
|
|
569
|
-
'once_on_transition_green',
|
|
570
|
-
'once_on_enter_green',
|
|
571
600
|
'once_on_after_go'
|
|
572
601
|
])
|
|
573
602
|
end
|
|
@@ -643,6 +672,10 @@ describe FiniteMachine, 'callbacks' do
|
|
|
643
672
|
expect(fsm.current).to eq(:initial)
|
|
644
673
|
fsm.bump
|
|
645
674
|
expect(callbacks).to eq([
|
|
675
|
+
'before_init_none_initial',
|
|
676
|
+
'exit_init_none_initial',
|
|
677
|
+
'enter_init_none_initial',
|
|
678
|
+
'after_init_none_initial',
|
|
646
679
|
'before_bump_initial_low',
|
|
647
680
|
'exit_bump_initial_low',
|
|
648
681
|
'enter_bump_initial_low',
|
|
@@ -650,6 +683,10 @@ describe FiniteMachine, 'callbacks' do
|
|
|
650
683
|
])
|
|
651
684
|
fsm.bump
|
|
652
685
|
expect(callbacks).to eq([
|
|
686
|
+
'before_init_none_initial',
|
|
687
|
+
'exit_init_none_initial',
|
|
688
|
+
'enter_init_none_initial',
|
|
689
|
+
'after_init_none_initial',
|
|
653
690
|
'before_bump_initial_low',
|
|
654
691
|
'exit_bump_initial_low',
|
|
655
692
|
'enter_bump_initial_low',
|
|
@@ -661,6 +698,10 @@ describe FiniteMachine, 'callbacks' do
|
|
|
661
698
|
])
|
|
662
699
|
fsm.bump
|
|
663
700
|
expect(callbacks).to eq([
|
|
701
|
+
'before_init_none_initial',
|
|
702
|
+
'exit_init_none_initial',
|
|
703
|
+
'enter_init_none_initial',
|
|
704
|
+
'after_init_none_initial',
|
|
664
705
|
'before_bump_initial_low',
|
|
665
706
|
'exit_bump_initial_low',
|
|
666
707
|
'enter_bump_initial_low',
|
|
@@ -699,11 +740,15 @@ describe FiniteMachine, 'callbacks' do
|
|
|
699
740
|
expect(fsm.current).to eq(:initial)
|
|
700
741
|
fsm.bump
|
|
701
742
|
expect(callbacks).to eq([
|
|
743
|
+
'before_init_none_initial',
|
|
744
|
+
'enter_init_none_initial',
|
|
702
745
|
'before_bump_initial_low',
|
|
703
746
|
'enter_bump_initial_low'
|
|
704
747
|
])
|
|
705
748
|
fsm.bump
|
|
706
749
|
expect(callbacks).to eq([
|
|
750
|
+
'before_init_none_initial',
|
|
751
|
+
'enter_init_none_initial',
|
|
707
752
|
'before_bump_initial_low',
|
|
708
753
|
'enter_bump_initial_low',
|
|
709
754
|
'before_bump_low_medium',
|
|
@@ -711,6 +756,8 @@ describe FiniteMachine, 'callbacks' do
|
|
|
711
756
|
])
|
|
712
757
|
fsm.bump
|
|
713
758
|
expect(callbacks).to eq([
|
|
759
|
+
'before_init_none_initial',
|
|
760
|
+
'enter_init_none_initial',
|
|
714
761
|
'before_bump_initial_low',
|
|
715
762
|
'enter_bump_initial_low',
|
|
716
763
|
'before_bump_low_medium',
|
|
@@ -719,4 +766,33 @@ describe FiniteMachine, 'callbacks' do
|
|
|
719
766
|
'enter_bump_medium_high'
|
|
720
767
|
])
|
|
721
768
|
end
|
|
769
|
+
|
|
770
|
+
it "permits state and event with the same name" do
|
|
771
|
+
called = []
|
|
772
|
+
fsm = FiniteMachine.define do
|
|
773
|
+
initial :on_hook
|
|
774
|
+
|
|
775
|
+
events {
|
|
776
|
+
event :off_hook, :on_hook => :off_hook
|
|
777
|
+
event :on_hook, :off_hook => :on_hook
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
callbacks {
|
|
781
|
+
on_before(:on_hook) { |event| called << "on_before_#{event.name}"}
|
|
782
|
+
on_enter(:on_hook) { |event| called << "on_enter_#{event.to}"}
|
|
783
|
+
}
|
|
784
|
+
end
|
|
785
|
+
expect(fsm.current).to eq(:on_hook)
|
|
786
|
+
expect(called).to eq([
|
|
787
|
+
'on_enter_on_hook'
|
|
788
|
+
])
|
|
789
|
+
fsm.off_hook
|
|
790
|
+
expect(fsm.current).to eq(:off_hook)
|
|
791
|
+
fsm.on_hook
|
|
792
|
+
expect(called).to eq([
|
|
793
|
+
'on_enter_on_hook',
|
|
794
|
+
'on_before_on_hook',
|
|
795
|
+
'on_enter_on_hook'
|
|
796
|
+
]);
|
|
797
|
+
end
|
|
722
798
|
end
|
data/spec/unit/define_spec.rb
CHANGED
|
@@ -49,11 +49,15 @@ describe FiniteMachine, 'initialize' do
|
|
|
49
49
|
event :stop, :yellow => :red
|
|
50
50
|
}
|
|
51
51
|
callbacks {
|
|
52
|
+
on_exit :none do |event| called << 'on_exit_none' end
|
|
52
53
|
on_enter :green do |event| called << 'on_enter_green' end
|
|
53
54
|
}
|
|
54
55
|
end
|
|
55
56
|
expect(fsm.current).to eql(:green)
|
|
56
|
-
expect(called).to
|
|
57
|
+
expect(called).to eq([
|
|
58
|
+
'on_exit_none',
|
|
59
|
+
'on_enter_green'
|
|
60
|
+
])
|
|
57
61
|
end
|
|
58
62
|
|
|
59
63
|
it "allows to specify initial state through parameter" do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: finite_machine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Piotr Murach
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-06-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|