anthonyw-simple_state 0.1.2 → 0.1.3
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.
- data/VERSION.yml +1 -1
- data/lib/simple_state/builder.rb +20 -6
- data/spec/event_methods_spec.rb +86 -58
- data/spec/predicate_methods_spec.rb +20 -0
- metadata +2 -2
data/VERSION.yml
CHANGED
data/lib/simple_state/builder.rb
CHANGED
@@ -30,7 +30,21 @@ module SimpleState
|
|
30
30
|
include ::SimpleState::Mixins
|
31
31
|
RUBY
|
32
32
|
|
33
|
+
# Create an anonymous module which will be added to the state machine
|
34
|
+
# class's inheritance chain.
|
35
|
+
mod = @mod = Module.new do
|
36
|
+
def self.inspect
|
37
|
+
"SimpleState::#{@klass}StateMachine"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Declare the state machine rules.
|
33
42
|
instance_eval(&blk)
|
43
|
+
|
44
|
+
# Insert the anonymous module.
|
45
|
+
@klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
46
|
+
include mod
|
47
|
+
RUBY
|
34
48
|
end
|
35
49
|
|
36
50
|
##
|
@@ -46,22 +60,22 @@ module SimpleState
|
|
46
60
|
@klass.states[name] = []
|
47
61
|
@klass.initial_state ||= name
|
48
62
|
|
49
|
-
@
|
63
|
+
@mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
50
64
|
def #{name}? # def prepared?
|
51
65
|
self.state == :#{name} # self.state == :prepared
|
52
66
|
end # end
|
53
67
|
RUBY
|
54
68
|
|
55
69
|
# Define transitions for this state.
|
56
|
-
StateBuilder.new(@klass, name).build(&blk) if blk
|
70
|
+
StateBuilder.new(@klass, @mod, name).build(&blk) if blk
|
57
71
|
end
|
58
72
|
|
59
73
|
##
|
60
74
|
# Responsible for building events for a given state.
|
61
75
|
#
|
62
76
|
class StateBuilder
|
63
|
-
def initialize(klass, state)
|
64
|
-
@klass, @state = klass, state
|
77
|
+
def initialize(klass, mod, state)
|
78
|
+
@klass, @module, @state = klass, mod, state
|
65
79
|
end
|
66
80
|
|
67
81
|
##
|
@@ -89,7 +103,7 @@ module SimpleState
|
|
89
103
|
# Keep track of valid transitions for this state.
|
90
104
|
@klass.states[@state].push([event, opts[:transitions_to]])
|
91
105
|
|
92
|
-
unless @
|
106
|
+
unless @module.method_defined?(:"#{event}!")
|
93
107
|
# Example:
|
94
108
|
#
|
95
109
|
# def process!
|
@@ -100,7 +114,7 @@ module SimpleState
|
|
100
114
|
# false
|
101
115
|
# end
|
102
116
|
# end
|
103
|
-
@
|
117
|
+
@module.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
104
118
|
def #{event}!
|
105
119
|
if self.class._valid_transition?(self.state, :#{event})
|
106
120
|
self.state =
|
data/spec/event_methods_spec.rb
CHANGED
@@ -1,91 +1,119 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
2
|
|
3
|
-
|
3
|
+
describe 'Generated event methods' do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
it 'should permit the use of super when overriding them' do
|
6
|
+
@c = Class.new do
|
7
|
+
attr_reader :called
|
8
|
+
|
9
|
+
extend SimpleState
|
10
|
+
|
11
|
+
state_machine do
|
12
|
+
state :begin do
|
13
|
+
event :go, :transitions_to => :finished
|
14
|
+
end
|
15
|
+
|
16
|
+
state :finished
|
10
17
|
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
def go!
|
20
|
+
@called = true
|
21
|
+
super()
|
22
|
+
end
|
23
|
+
end.new
|
15
24
|
|
16
|
-
|
17
|
-
@c.go
|
25
|
+
@c.should be_begin
|
26
|
+
lambda { @c.go! }.should_not raise_error(NoMethodError)
|
27
|
+
@c.should be_finished
|
28
|
+
@c.called.should be_true
|
18
29
|
end
|
19
30
|
|
20
|
-
|
21
|
-
@c.go!
|
22
|
-
@c.should be_state_one
|
23
|
-
end
|
24
|
-
end
|
31
|
+
# Event Validation =========================================================
|
25
32
|
|
26
|
-
describe '
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
describe 'when the transition is valid' do
|
34
|
+
before(:each) do
|
35
|
+
@c = state_class do
|
36
|
+
state :begin do
|
37
|
+
event :go, :transitions_to => :state_one
|
38
|
+
end
|
32
39
|
|
33
|
-
|
34
|
-
event :go_again, :transitions_to => :state_two
|
40
|
+
state :state_one
|
35
41
|
end
|
42
|
+
end
|
36
43
|
|
37
|
-
|
44
|
+
it 'should return the new state' do
|
45
|
+
@c.go!.should == :state_one
|
38
46
|
end
|
39
|
-
end
|
40
47
|
|
41
|
-
|
42
|
-
|
48
|
+
it 'should transition the instance to the new state' do
|
49
|
+
@c.go!
|
50
|
+
@c.should be_state_one
|
51
|
+
end
|
43
52
|
end
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
describe 'when the transition is not valid' do
|
55
|
+
before(:each) do
|
56
|
+
@c = state_class do
|
57
|
+
state :begin do
|
58
|
+
event :go, :transitions_to => :state_one
|
59
|
+
end
|
60
|
+
|
61
|
+
state :state_one do
|
62
|
+
event :go_again, :transitions_to => :state_two
|
63
|
+
end
|
64
|
+
|
65
|
+
state :state_two
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return false' do
|
70
|
+
@c.go_again!.should be_false
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not change the instance's state" do
|
74
|
+
@c.go_again!
|
75
|
+
@c.should be_begin
|
76
|
+
end
|
48
77
|
end
|
49
|
-
end
|
50
78
|
|
79
|
+
# Multiple Paths Definition ================================================
|
51
80
|
|
52
|
-
|
81
|
+
describe 'when mulitple states share the same event' do
|
82
|
+
before(:each) do
|
83
|
+
@path = state_class do
|
84
|
+
state :begin do
|
85
|
+
event :s1, :transitions_to => :state_one
|
86
|
+
event :s2, :transitions_to => :state_two
|
87
|
+
end
|
53
88
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
state :begin do
|
58
|
-
event :s1, :transitions_to => :state_one
|
59
|
-
event :s2, :transitions_to => :state_two
|
60
|
-
end
|
89
|
+
state :state_one do
|
90
|
+
event :go, :transitions_to => :state_three
|
91
|
+
end
|
61
92
|
|
62
|
-
|
63
|
-
|
64
|
-
|
93
|
+
state :state_two do
|
94
|
+
event :go, :transitions_to => :state_four
|
95
|
+
end
|
65
96
|
|
66
|
-
|
67
|
-
|
97
|
+
state :state_three
|
98
|
+
state :state_four
|
68
99
|
end
|
100
|
+
end
|
69
101
|
|
70
|
-
|
71
|
-
|
102
|
+
it 'should transition to state_three if currently in state_one' do
|
103
|
+
@path.s1!
|
104
|
+
@path.go!
|
105
|
+
@path.should be_state_three
|
72
106
|
end
|
73
|
-
end
|
74
107
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
108
|
+
it 'should transition to state_four if current in state_two' do
|
109
|
+
@path.s2!
|
110
|
+
@path.go!
|
111
|
+
@path.should be_state_four
|
112
|
+
end
|
79
113
|
end
|
80
114
|
|
81
|
-
it 'should transition to state_four if current in state_two' do
|
82
|
-
@path.s2!
|
83
|
-
@path.go!
|
84
|
-
@path.should be_state_four
|
85
|
-
end
|
86
115
|
end
|
87
116
|
|
88
|
-
|
89
117
|
# Test full workflow =========================================================
|
90
118
|
# This tests all the possible transition permutations of a state machine.
|
91
119
|
|
@@ -17,4 +17,24 @@ describe SimpleState, 'generated predicate methods' do
|
|
17
17
|
@predicate_test.should_not be_state_two
|
18
18
|
@predicate_test.should_not be_state_three
|
19
19
|
end
|
20
|
+
|
21
|
+
it 'should permit the use of super when overriding them' do
|
22
|
+
@c = Class.new do
|
23
|
+
attr_reader :called
|
24
|
+
|
25
|
+
extend SimpleState
|
26
|
+
|
27
|
+
state_machine do
|
28
|
+
state :begin
|
29
|
+
end
|
30
|
+
|
31
|
+
def begin?
|
32
|
+
@called = true
|
33
|
+
super()
|
34
|
+
end
|
35
|
+
end.new
|
36
|
+
|
37
|
+
lambda { @c.begin? }.should_not raise_error(NoMethodError)
|
38
|
+
@c.called.should be_true
|
39
|
+
end
|
20
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anthonyw-simple_state
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anthony Williams
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-03-
|
12
|
+
date: 2009-03-10 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|