ruby-state-machine 0.0.3 → 0.0.4
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/History.txt +7 -0
- data/Manifest.txt +2 -0
- data/PostInstall.txt +1 -7
- data/README.rdoc +3 -3
- data/Rakefile +0 -0
- data/config/website.yml +1 -1
- data/lib/ruby-state-machine.rb +1 -1
- data/lib/ruby-state-machine/bounded_array.rb +8 -0
- data/lib/ruby-state-machine/state_machine.rb +242 -0
- data/test/test_helper.rb +0 -0
- data/test/test_state_machine.rb +0 -0
- data/website/index.html +31 -14
- data/website/index.txt +26 -12
- data/website/javascripts/rounded_corners_lite.inc.js +0 -0
- data/website/stylesheets/screen.css +0 -0
- data/website/template.html.erb +0 -0
- metadata +4 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/PostInstall.txt
CHANGED
@@ -1,7 +1 @@
|
|
1
|
-
|
2
|
-
For more information on ruby-state-machine, see http://ruby-state-machine.rubyforge.org
|
3
|
-
|
4
|
-
NOTE: Change this information in PostInstall.txt
|
5
|
-
You can also delete it if you don't want it.
|
6
|
-
|
7
|
-
|
1
|
+
For more information on ruby-state-machine, see http://ruby-state-mach.rubyforge.org
|
data/README.rdoc
CHANGED
@@ -16,17 +16,17 @@ FIX (describe your package)
|
|
16
16
|
|
17
17
|
== REQUIREMENTS:
|
18
18
|
|
19
|
-
*
|
19
|
+
* None
|
20
20
|
|
21
21
|
== INSTALL:
|
22
22
|
|
23
|
-
*
|
23
|
+
* sudo gem install ruby-state-machine
|
24
24
|
|
25
25
|
== LICENSE:
|
26
26
|
|
27
27
|
(The MIT License)
|
28
28
|
|
29
|
-
Copyright (c) 2009
|
29
|
+
Copyright (c) 2007-2009 Steven Miers
|
30
30
|
|
31
31
|
Permission is hereby granted, free of charge, to any person obtaining
|
32
32
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
File without changes
|
data/config/website.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
host: stevenmiers@rubyforge.org
|
2
|
-
remote_dir: /var/www/gforge-projects/ruby-state-
|
2
|
+
remote_dir: /var/www/gforge-projects/ruby-state-mach
|
data/lib/ruby-state-machine.rb
CHANGED
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'ruby-state-machine/bounded_array'
|
2
|
+
|
3
|
+
# StateMachine
|
4
|
+
# Simple and flexible state machine. Define a state machine with an array of states,
|
5
|
+
# an array of events, and one or more transition actions. A transition can be
|
6
|
+
# as simple as the symbol for the next state, a lambda (code) to execute. Primitive
|
7
|
+
# branching can also be achieved if necessary by using a "decider" instance method.
|
8
|
+
# Please see StateMachine.state_transition for full details on the variations
|
9
|
+
# available. StateMachineTest also contains examples and unit tests for most (if not all)
|
10
|
+
# of the available functionality. See README for example.
|
11
|
+
module StateMachine
|
12
|
+
def self.included(base)
|
13
|
+
base.extend StateMachine::ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
attr_accessor :machine
|
19
|
+
|
20
|
+
# Create state machine with the following options:
|
21
|
+
# states Array[symbols], each symbol is name of state
|
22
|
+
# events Array[symbols], each symbol is name of event
|
23
|
+
# default_state symbol, symbol is one of states
|
24
|
+
def state_machine(opts)
|
25
|
+
@machine = StateMachine::Machine.new(opts)
|
26
|
+
self.send(:include, StateMachine::InstanceMethods)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add a transition to state machine with the following keys:
|
30
|
+
# :state=>state (symbol) for which transition is being declared
|
31
|
+
# :event=>event (symbol) which causes transition
|
32
|
+
# :decider=>name of instance method on state machine specialization that "decides"
|
33
|
+
# next state in case of multiple actions for next state (see below).
|
34
|
+
# Method in question should return name of next state, or name of action
|
35
|
+
# if actions are named (not required).
|
36
|
+
# :next=>action to take for this transition, one of:
|
37
|
+
# 1) state name(symbol), or special symbol (:stay), which stays at current state
|
38
|
+
# 2) hash{:state=>state name(symbol), :action=>code/lambda(string), :name=>id of action, for decider}
|
39
|
+
# 3) array of 1 and/or 2. Decider required in this case.
|
40
|
+
#
|
41
|
+
# Example 1:
|
42
|
+
# state_transition :state=>:c_state, :event=>:w_event, :decider => :c_state_decider,
|
43
|
+
# :next=>[
|
44
|
+
# {:state=>:a_state, :action=>lambda{|o, args| o.increment_value(7)} },
|
45
|
+
# {:state=>:b_state, :action=>lambda{|o, args| o.increment_value(-10)} }
|
46
|
+
# ]
|
47
|
+
#
|
48
|
+
# Example 2 (stays at current state):
|
49
|
+
# state_transition :state=>:c_state, :event=>:y_event, :next=>{:state=>:stay, :action=>lambda{|o, args| o.increment_value(-3)}}
|
50
|
+
#
|
51
|
+
# Example 3:
|
52
|
+
# state_transition :state=>:b_state, :event=>:z_event, :next=>:a_state
|
53
|
+
def state_transition(opts)
|
54
|
+
@machine.add_transition(opts)
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_state; @machine.default_state; end
|
58
|
+
def states; @machine.states; end
|
59
|
+
def events; @machine.events; end
|
60
|
+
def transitions; @machine.transitions; end
|
61
|
+
def next_state(*args); @machine.next_state(*args); end
|
62
|
+
def next_state_instruction(*args); @machine.next_state_instruction(*args); end
|
63
|
+
end
|
64
|
+
|
65
|
+
module InstanceMethods
|
66
|
+
attr_accessor :event_history
|
67
|
+
|
68
|
+
def initialize(args=nil)
|
69
|
+
@current_state = default_state
|
70
|
+
@event_history = BoundedArray.new
|
71
|
+
#puts "Current state is #{@current_state} #{@current_state.class}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def send_event(event)
|
75
|
+
# puts "Sending event: #{event}"
|
76
|
+
check_current_state
|
77
|
+
next_state_instruction = self.class.next_state_instruction(@current_state, event)
|
78
|
+
if next_state_instruction.nil?
|
79
|
+
cs = @current_state
|
80
|
+
@current_state = default_state
|
81
|
+
puts "Returned to default state: [#{@current_state}]."
|
82
|
+
raise InvalidStateError, "No valid next state for #{cs} using event #{event} (#{cs.class}/#{event.class})."
|
83
|
+
end
|
84
|
+
|
85
|
+
if(next_state_instruction)
|
86
|
+
if(!String(next_state_instruction[:decider]).empty?)
|
87
|
+
# Decider present, call method:
|
88
|
+
decide_id = execute(next_state_instruction[:decider], event)
|
89
|
+
|
90
|
+
# Error checking:
|
91
|
+
if String(decide_id).empty?
|
92
|
+
raise InvalidStateError,
|
93
|
+
"Decider returned blank/nil for #{@current_state} using event #{event}. Next state from decider: [#{decide_id.inspect}]. Possible next states are [#{next_state_instruction[:next].inspect}]"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Find next state:
|
97
|
+
instruction = Array(next_state_instruction[:next]).detect { |i|
|
98
|
+
i[:state].to_sym==decide_id.to_sym or i[:name].to_sym==decide_id.to_sym
|
99
|
+
}
|
100
|
+
|
101
|
+
# Error checking:
|
102
|
+
if instruction.nil?
|
103
|
+
raise InvalidStateError,
|
104
|
+
"No valid next instruction for #{@current_state} using event #{event}. Next state from decider: [#{decide_id.inspect}(#{decide_id.class})]. Possible next states are [#{next_state_instruction[:next].inspect}]"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Do it:
|
108
|
+
process_instruction(instruction, event)
|
109
|
+
else
|
110
|
+
# Do it:
|
111
|
+
process_instruction(next_state_instruction[:next], event)
|
112
|
+
end
|
113
|
+
@current_state
|
114
|
+
end
|
115
|
+
@event_history.push(event)
|
116
|
+
end
|
117
|
+
|
118
|
+
def current_state
|
119
|
+
check_current_state
|
120
|
+
@current_state
|
121
|
+
end
|
122
|
+
|
123
|
+
def current_state=state
|
124
|
+
@current_state = state.to_sym
|
125
|
+
end
|
126
|
+
|
127
|
+
def default_state
|
128
|
+
(self.class.default_state) ? self.class.default_state : self.class.states.first
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def process_instruction(instruction, event)
|
134
|
+
if instruction.nil?
|
135
|
+
@current_state = default_state
|
136
|
+
puts "Returned to default state: [#{@current_state}]."
|
137
|
+
raise InvalidStateError, "No valid next instruction for #{@current_state} using event #{event}"
|
138
|
+
end
|
139
|
+
|
140
|
+
if(instruction.is_a?Symbol)
|
141
|
+
change_state(instruction)
|
142
|
+
else
|
143
|
+
#puts "Processing action: #{instruction[:action]}"
|
144
|
+
execute(instruction[:action], event)
|
145
|
+
change_state(instruction[:state])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def execute(action, event)
|
150
|
+
unless action.nil?
|
151
|
+
if Symbol === action
|
152
|
+
self.method(action).call(:event=>event)
|
153
|
+
else
|
154
|
+
action.call(self, :event=>event)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def change_state(state_sym)
|
160
|
+
case(state_sym)
|
161
|
+
when :back
|
162
|
+
raise InvalidStateError, "Back is reserved but not yet implemented."
|
163
|
+
when :stay
|
164
|
+
@current_state = @current_state # nop, but should queue
|
165
|
+
else
|
166
|
+
@current_state = state_sym
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def check_current_state
|
171
|
+
raise InvalidStateError, "No valid current state. Please call super() from state machine impl." if @current_state.nil?
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
class Machine
|
177
|
+
attr_accessor :states
|
178
|
+
attr_accessor :events
|
179
|
+
attr_accessor :transitions
|
180
|
+
attr_accessor :default_state
|
181
|
+
|
182
|
+
def initialize(opts)
|
183
|
+
@states=opts[:states].collect{|state| state.to_sym}
|
184
|
+
@events=opts[:events].collect{|event| event.to_sym}
|
185
|
+
@default_state=opts[:default_state].to_sym if opts[:default_state]
|
186
|
+
@transitions=[]
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_transition(opts)
|
190
|
+
new_opts=strings_to_sym(opts)
|
191
|
+
|
192
|
+
# Some validation for arrays of actions:
|
193
|
+
if (new_opts[:next].is_a?Array)
|
194
|
+
if new_opts[:next].length==1
|
195
|
+
new_opts[:next] = new_opts[:next].first
|
196
|
+
elsif new_opts[:next].length>1
|
197
|
+
raise ArgumentError, "A decider must be present for multiple actions." if String(new_opts[:decider]).empty?
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
@transitions << new_opts
|
202
|
+
end
|
203
|
+
|
204
|
+
def strings_to_sym(hash)
|
205
|
+
new_hash=hash.dup
|
206
|
+
hash.each do |k, v|
|
207
|
+
unless (v.nil? or (v.respond_to?:empty? and v.empty? ))
|
208
|
+
if (v.is_a?(Hash))
|
209
|
+
new_hash[k] = strings_to_sym(v)
|
210
|
+
elsif (v.is_a?(Array))
|
211
|
+
new_array = v.dup
|
212
|
+
v.each_with_index do |array_hash, index|
|
213
|
+
new_array[index] = strings_to_sym(array_hash) if array_hash.is_a?(Hash)
|
214
|
+
end
|
215
|
+
new_hash[k]=new_array
|
216
|
+
elsif (v.is_a?(String))
|
217
|
+
new_hash[k] = v.to_sym
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
new_hash
|
222
|
+
end
|
223
|
+
|
224
|
+
# Next state (symbol only) for given state and event.
|
225
|
+
# (equivalent to next_state_instruction(state, event)[:next_state])
|
226
|
+
def next_state(state, event)
|
227
|
+
transition = next_state_instruction(state, event)
|
228
|
+
ns = transition ? transition[:next] : nil
|
229
|
+
(ns.is_a?Symbol) ? ns : ns && ns[:state]
|
230
|
+
end
|
231
|
+
|
232
|
+
# Next state instruction (as hash) for given state and event:
|
233
|
+
def next_state_instruction(state, event)
|
234
|
+
@transitions.detect{|t| t[:state]==state and t[:event]==event}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
class InvalidStateError < Exception #:nodoc:
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
data/test/test_helper.rb
CHANGED
File without changes
|
data/test/test_state_machine.rb
CHANGED
File without changes
|
data/website/index.html
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
6
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
7
|
<title>
|
8
|
-
ruby
|
8
|
+
ruby-state-machine
|
9
9
|
</title>
|
10
10
|
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
11
|
<style>
|
@@ -30,21 +30,41 @@
|
|
30
30
|
<body>
|
31
31
|
<div id="main">
|
32
32
|
|
33
|
-
<h1>ruby
|
33
|
+
<h1>ruby-state-machine</h1>
|
34
34
|
<div class="sidebar">
|
35
|
-
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ruby-state-
|
35
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ruby-state-mach"; return false'>
|
36
36
|
<p>Get Version</p>
|
37
|
-
<a href="http://rubyforge.org/projects/ruby-state-
|
37
|
+
<a href="http://rubyforge.org/projects/ruby-state-mach" class="numbers">0.0.3</a>
|
38
38
|
</div>
|
39
39
|
</div>
|
40
|
-
<
|
40
|
+
<p>An enhanced state machine gem for ruby (doesn’t require Rails). Provides more robust <span class="caps">DSL</span> state declaration syntax than other state machines. Multiple “actions” per event (i.e., next state, labmda, or a “decider”. Fully unit-tested & documented. Has been used in production for over 2 years.</p>
|
41
41
|
<h2>Installing</h2>
|
42
42
|
<p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">ruby</span><span class="punct">-</span><span class="ident">state</span><span class="punct">-</span><span class="ident">machine</span></pre></p>
|
43
|
-
<h2>
|
44
|
-
<
|
43
|
+
<h2>Demonstration of usage<br />
|
44
|
+
<pre class='syntax'>
|
45
|
+
<span class="keyword">class </span><span class="class">SampleMachine</span>
|
46
|
+
<span class="ident">include</span> <span class="constant">StateMachine</span>
|
47
|
+
<span class="ident">state_machine</span> <span class="symbol">:states</span> <span class="punct">=></span> <span class="punct">[</span><span class="symbol">:a_state</span><span class="punct">,</span> <span class="symbol">:b_state</span><span class="punct">,</span> <span class="symbol">:c_state</span><span class="punct">,</span> <span class="symbol">:d_state</span><span class="punct">],</span> <span class="symbol">:events</span> <span class="punct">=></span> <span class="punct">[</span><span class="symbol">:w_event</span><span class="punct">,</span> <span class="symbol">:x_event</span><span class="punct">,</span> <span class="symbol">:y_event</span><span class="punct">,</span> <span class="symbol">:z_event</span><span class="punct">]</span>
|
48
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:a_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:x_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:c_state</span>
|
49
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:a_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:y_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:a_state</span>
|
50
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:a_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:z_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:b_state</span>
|
51
|
+
|
52
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:b_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:w_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:b_state</span>
|
53
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:b_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:y_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:c_state</span>
|
54
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:b_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:z_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:a_state</span>
|
55
|
+
|
56
|
+
<span class="ident">state_transition</span> <span class="symbol">:state=</span><span class="punct">></span><span class="symbol">:c_state</span><span class="punct">,</span> <span class="symbol">:event=</span><span class="punct">></span><span class="symbol">:x_event</span><span class="punct">,</span> <span class="symbol">:next=</span><span class="punct">></span><span class="symbol">:b_state</span>
|
57
|
+
<span class="keyword">end</span>
|
58
|
+
|
59
|
+
<span class="ident">sm</span> <span class="punct">=</span> <span class="constant">SampleMachine</span><span class="punct">.</span><span class="ident">new</span>
|
60
|
+
<span class="ident">assert_equal</span><span class="punct">(</span><span class="symbol">:a_state</span><span class="punct">,</span> <span class="ident">sm</span><span class="punct">.</span><span class="ident">current_state</span><span class="punct">)</span>
|
61
|
+
<span class="ident">sm</span><span class="punct">.</span><span class="ident">send_event</span><span class="punct">(</span><span class="symbol">:x_event</span><span class="punct">)</span>
|
62
|
+
<span class="ident">assert_equal</span><span class="punct">(</span><span class="symbol">:c_state</span><span class="punct">,</span> <span class="ident">sm</span><span class="punct">.</span><span class="ident">current_state</span><span class="punct">)</span>
|
63
|
+
|
64
|
+
</pre></h2>
|
65
|
+
<p>For examples of other functionality, including branching, deciders, lambdas, etc, see test/test_state_machine.</p>
|
45
66
|
<h2>Forum</h2>
|
46
67
|
<p><a href="http://groups.google.com/group/ruby-state-machine">http://groups.google.com/group/ruby-state-machine</a></p>
|
47
|
-
<p><span class="caps">TODO</span> – create Google Group – ruby-state-machine</p>
|
48
68
|
<h2>How to submit patches</h2>
|
49
69
|
<p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people’s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
|
50
70
|
<p><span class="caps">TODO</span> – pick <span class="caps">SVN</span> or Git instructions</p>
|
@@ -52,12 +72,9 @@
|
|
52
72
|
<p><span class="caps">OOOORRRR</span></p>
|
53
73
|
<p>You can fetch the source from either:</p>
|
54
74
|
<ul>
|
55
|
-
<li>rubyforge: <
|
75
|
+
<li>rubyforge: <a href="http://rubyforge.org/scm/?group_id=8855">http://rubyforge.org/scm/?group_id=8855</a></li>
|
56
76
|
</ul>
|
57
|
-
<
|
58
|
-
yet to refresh your local rubyforge data with this projects’ id information.</p>
|
59
|
-
<p>When you do this, this message will magically disappear!</p>
|
60
|
-
<p>Or you can hack website/index.txt and make it all go away!!</p>
|
77
|
+
<pre>git clone git://rubyforge.org/ruby-state-machine.git</pre>
|
61
78
|
<ul>
|
62
79
|
<li>github: <a href="http://github.com/GITHUB_USERNAME/ruby-state-machine/tree/master">http://github.com/GITHUB_USERNAME/ruby-state-machine/tree/master</a></li>
|
63
80
|
</ul>
|
@@ -70,7 +87,7 @@ yet to refresh your local rubyforge data with this projects’ id informatio
|
|
70
87
|
<h3>Build and test instructions</h3>
|
71
88
|
<pre>cd ruby-state-machine
|
72
89
|
rake test
|
73
|
-
|
90
|
+
</pre>
|
74
91
|
<h2>License</h2>
|
75
92
|
<p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
|
76
93
|
<h2>Contact</h2>
|
data/website/index.txt
CHANGED
@@ -1,26 +1,40 @@
|
|
1
|
-
h1. ruby
|
2
|
-
|
3
|
-
|
4
|
-
h2. What
|
1
|
+
h1. ruby-state-machine
|
5
2
|
|
3
|
+
An enhanced state machine gem for ruby (doesn't require Rails). Provides more robust DSL state declaration syntax than other state machines. Multiple "actions" per event (i.e., next state, labmda, or a "decider". Fully unit-tested & documented. Has been used in production for over 2 years.
|
6
4
|
|
7
5
|
h2. Installing
|
8
6
|
|
9
7
|
<pre syntax="ruby">sudo gem install ruby-state-machine</pre>
|
10
8
|
|
11
|
-
h2. The basics
|
12
|
-
|
13
|
-
|
14
9
|
h2. Demonstration of usage
|
15
|
-
|
16
|
-
|
10
|
+
<pre syntax="ruby">
|
11
|
+
class SampleMachine
|
12
|
+
include StateMachine
|
13
|
+
state_machine :states => [:a_state, :b_state, :c_state, :d_state], :events => [:w_event, :x_event, :y_event, :z_event]
|
14
|
+
state_transition :state=>:a_state, :event=>:x_event, :next=>:c_state
|
15
|
+
state_transition :state=>:a_state, :event=>:y_event, :next=>:a_state
|
16
|
+
state_transition :state=>:a_state, :event=>:z_event, :next=>:b_state
|
17
|
+
|
18
|
+
state_transition :state=>:b_state, :event=>:w_event, :next=>:b_state
|
19
|
+
state_transition :state=>:b_state, :event=>:y_event, :next=>:c_state
|
20
|
+
state_transition :state=>:b_state, :event=>:z_event, :next=>:a_state
|
21
|
+
|
22
|
+
state_transition :state=>:c_state, :event=>:x_event, :next=>:b_state
|
23
|
+
end
|
24
|
+
|
25
|
+
sm = SampleMachine.new
|
26
|
+
assert_equal(:a_state, sm.current_state)
|
27
|
+
sm.send_event(:x_event)
|
28
|
+
assert_equal(:c_state, sm.current_state)
|
29
|
+
|
30
|
+
</pre>
|
31
|
+
|
32
|
+
For examples of other functionality, including branching, deciders, lambdas, etc, see test/test_state_machine.
|
17
33
|
|
18
34
|
h2. Forum
|
19
35
|
|
20
36
|
"http://groups.google.com/group/ruby-state-machine":http://groups.google.com/group/ruby-state-machine
|
21
37
|
|
22
|
-
TODO - create Google Group - ruby-state-machine
|
23
|
-
|
24
38
|
h2. How to submit patches
|
25
39
|
|
26
40
|
Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
|
@@ -68,7 +82,7 @@ h3. Build and test instructions
|
|
68
82
|
|
69
83
|
<pre>cd ruby-state-machine
|
70
84
|
rake test
|
71
|
-
|
85
|
+
</pre>
|
72
86
|
|
73
87
|
|
74
88
|
h2. License
|
File without changes
|
File without changes
|
data/website/template.html.erb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-state-machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stevenmiers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-19 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,8 @@ files:
|
|
42
42
|
- Rakefile
|
43
43
|
- config/website.yml
|
44
44
|
- lib/ruby-state-machine.rb
|
45
|
+
- lib/ruby-state-machine/bounded_array.rb
|
46
|
+
- lib/ruby-state-machine/state_machine.rb
|
45
47
|
- script/console
|
46
48
|
- script/destroy
|
47
49
|
- script/generate
|