ruby-state-machine 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|