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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ac2b8cf6f6e899a7d6b2f04c240703d45a4b67d
4
- data.tar.gz: f556b050c651d3120b5a2fe990fd1efc94abf961
3
+ metadata.gz: d0521fc82d97ac5139abe2fcea0ed72532af05fe
4
+ data.tar.gz: 260b8c31a86e2c3f80018aad2640c62222cea2af
5
5
  SHA512:
6
- metadata.gz: f5871e7adbd4a10e4a44a9bd4916f09843890490fd967d9bc8ce7b7c0a20033b72f2344d23fd7cd6bd2a3369cc5f622f343ea3ce1c2b817e8332909d754806fe
7
- data.tar.gz: a1feb862d90d7da38db41ce326ab3a9dbcc241555a4d65e216eeb4260442f5d1a942ac474551f2b41853ab7bb6b5aeb62b474e7efab2bb2571c22a0bfe0da0bf
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
@@ -1,3 +1,8 @@
1
+ 0.7.1 (June 8, 2014)
2
+
3
+ * Change to relax callback name checks to allow for duplicate state and event names
4
+ * Change so that transition to initial state triggers callbacks
5
+
1
6
  0.7.0 (May 26, 2014)
2
7
 
3
8
  * Change Event to EventHook for callback events
data/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  [![Build Status](https://secure.travis-ci.org/peter-murach/finite_machine.png?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/peter-murach/finite_machine.png)][codeclimate]
5
5
  [![Coverage Status](https://coveralls.io/repos/peter-murach/finite_machine/badge.png)][coverage]
6
- [![Inline docs](http://inch-pages.github.io/github/peter-murach/finite_machine.png)][inchpages]
6
+ [![Inline docs](http://inch-ci.org/github/peter-murach/finite_machine.png)][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-pages.github.io/github/peter-murach/finite_machine
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
 
@@ -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
@@ -68,12 +68,17 @@ module FiniteMachine
68
68
  # @api public
69
69
  def initial(value)
70
70
  state, name, self.defer = parse(value)
71
- unless defer
72
- machine.state = state
73
- machine.initial_state = state
74
- end
75
- event = proc { event name, from: FiniteMachine::DEFAULT_STATE, to: state }
76
- machine.events_dsl.call(&event)
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 machine.states.include?(name) &&
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 machine.event_names.include?(name) &&
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module FiniteMachine
4
- VERSION = "0.7.0"
4
+ VERSION = "0.7.1"
5
5
  end
@@ -91,8 +91,9 @@ describe FiniteMachine, 'async_events' do
91
91
  expect(called).to match_array([
92
92
  'on_enter_green',
93
93
  'on_before_slow',
94
- 'on_after_go',
95
- 'on_exit_yellow'
94
+ 'on_exit_yellow',
95
+ 'on_enter_green',
96
+ 'on_after_go'
96
97
  ])
97
98
  end
98
99
  end
@@ -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
@@ -43,7 +43,7 @@ describe FiniteMachine, 'define' do
43
43
  fsm.handle(FiniteMachine::InvalidStateError) { |exception|
44
44
  called << 'error_handler'
45
45
  }
46
-
46
+ fsm.init
47
47
  expect(fsm.current).to eql(:green)
48
48
  fsm.slow
49
49
  expect(fsm.current).to eql(:yellow)
@@ -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 be_empty
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.0
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-05-26 00:00:00.000000000 Z
11
+ date: 2014-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler