state_machine 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +26 -0
- data/README.rdoc +254 -46
- data/Rakefile +29 -3
- data/examples/AutoShop_state.png +0 -0
- data/examples/Car_state.jpg +0 -0
- data/examples/Vehicle_state.png +0 -0
- data/lib/state_machine.rb +161 -116
- data/lib/state_machine/assertions.rb +21 -0
- data/lib/state_machine/callback.rb +168 -0
- data/lib/state_machine/eval_helpers.rb +67 -0
- data/lib/state_machine/event.rb +135 -101
- data/lib/state_machine/extensions.rb +83 -0
- data/lib/state_machine/guard.rb +115 -0
- data/lib/state_machine/integrations/active_record.rb +242 -0
- data/lib/state_machine/integrations/data_mapper.rb +198 -0
- data/lib/state_machine/integrations/data_mapper/observer.rb +153 -0
- data/lib/state_machine/integrations/sequel.rb +169 -0
- data/lib/state_machine/machine.rb +746 -352
- data/lib/state_machine/transition.rb +104 -212
- data/test/active_record.log +34865 -0
- data/test/classes/switch.rb +11 -0
- data/test/data_mapper.log +14015 -0
- data/test/functional/state_machine_test.rb +249 -15
- data/test/sequel.log +3835 -0
- data/test/test_helper.rb +3 -12
- data/test/unit/assertions_test.rb +13 -0
- data/test/unit/callback_test.rb +189 -0
- data/test/unit/eval_helpers_test.rb +92 -0
- data/test/unit/event_test.rb +247 -113
- data/test/unit/guard_test.rb +420 -0
- data/test/unit/integrations/active_record_test.rb +515 -0
- data/test/unit/integrations/data_mapper_test.rb +407 -0
- data/test/unit/integrations/sequel_test.rb +244 -0
- data/test/unit/invalid_transition_test.rb +1 -1
- data/test/unit/machine_test.rb +1056 -98
- data/test/unit/state_machine_test.rb +14 -113
- data/test/unit/transition_test.rb +269 -495
- metadata +44 -30
- data/test/app_root/app/models/auto_shop.rb +0 -34
- data/test/app_root/app/models/car.rb +0 -19
- data/test/app_root/app/models/highway.rb +0 -3
- data/test/app_root/app/models/motorcycle.rb +0 -3
- data/test/app_root/app/models/switch.rb +0 -23
- data/test/app_root/app/models/switch_observer.rb +0 -20
- data/test/app_root/app/models/toggle_switch.rb +0 -2
- data/test/app_root/app/models/vehicle.rb +0 -78
- data/test/app_root/config/environment.rb +0 -7
- data/test/app_root/db/migrate/001_create_switches.rb +0 -12
- data/test/app_root/db/migrate/002_create_auto_shops.rb +0 -13
- data/test/app_root/db/migrate/003_create_highways.rb +0 -11
- data/test/app_root/db/migrate/004_create_vehicles.rb +0 -16
- data/test/factory.rb +0 -77
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
== master
|
2
2
|
|
3
|
+
== 0.4.0 / 2008-12-14
|
4
|
+
|
5
|
+
* Remove the PluginAWeek namespace
|
6
|
+
* Add generic attribute predicate (e.g. "#{attribute}?(state_name)") and state predicates (e.g. "#{state}?")
|
7
|
+
* Add Sequel support
|
8
|
+
* Fix aliasing :initialize on ActiveRecord models causing warnings when the environment is reloaded
|
9
|
+
* Fix ActiveRecord state machines trying to query the database on unmigrated models
|
10
|
+
* Fix initial states not getting set when the current value is an empty string [Aaron Gibralter]
|
11
|
+
* Add rake tasks for generating graphviz files for state machines [Nate Murray]
|
12
|
+
* Fix initial state not being included in list of known states
|
13
|
+
* Add other_states directive for defining additional states not referenced in transitions or callbacks [Pete Forde]
|
14
|
+
* Add next_#{event}_transition for getting the next transition that would be performed if the event were invoked
|
15
|
+
* Add the ability to override the pluralized name of an attribute for creating scopes
|
16
|
+
* Add the ability to halt callback chains by: throw :halt
|
17
|
+
* Add support for dynamic to states in transitions (e.g. :to => lambda {Time.now})
|
18
|
+
* Add support for using real blocks in before_transition/after_transition calls instead of using the :do option
|
19
|
+
* Add DataMapper support
|
20
|
+
* Include states referenced in transition callbacks in the list of a machine's known states
|
21
|
+
* Only generate the known states for a machine on demand, rather than calculating beforehand
|
22
|
+
* Add the ability to skip state change actions during a transition (e.g. vehicle.ignite(false))
|
23
|
+
* Add the ability for the state change action (e.g. +save+ for ActiveRecord) to be configurable
|
24
|
+
* Allow state machines to be defined on *any* Ruby class, not just ActiveRecord (removes all external dependencies)
|
25
|
+
* Refactor transitions, guards, and callbacks for better organization/design
|
26
|
+
* Use a class containing the transition context in callbacks, rather than an ordered list of each individual attribute
|
27
|
+
* Add without_#{attribute} named scopes (opposite of the existing with_#{attribute} named scopes) [Sean O'Brien]
|
28
|
+
|
3
29
|
== 0.3.1 / 2008-10-26
|
4
30
|
|
5
31
|
* Fix the initial state not getting set when the state attribute is mass-assigned but protected
|
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
== state_machine
|
2
2
|
|
3
|
-
+state_machine+ adds support for creating state machines for attributes
|
4
|
-
|
3
|
+
+state_machine+ adds support for creating state machines for attributes on any
|
4
|
+
Ruby class.
|
5
5
|
|
6
6
|
== Resources
|
7
7
|
|
@@ -23,16 +23,29 @@ Source
|
|
23
23
|
|
24
24
|
== Description
|
25
25
|
|
26
|
-
State machines make it dead-simple to manage the behavior of a
|
27
|
-
the status of
|
28
|
-
|
29
|
-
|
30
|
-
increase.
|
26
|
+
State machines make it dead-simple to manage the behavior of a class. Too often,
|
27
|
+
the status of an object is kept by creating multiple boolean attributes and
|
28
|
+
deciding how to behave based on the values. This can become cumbersome and
|
29
|
+
difficult to maintain when the complexity of your class starts to increase.
|
31
30
|
|
32
31
|
+state_machine+ simplifies this design by introducing the various parts of a real
|
33
|
-
state machine, including states, events, and
|
34
|
-
designed to be
|
35
|
-
|
32
|
+
state machine, including states, events, transitions, and callbacks. However,
|
33
|
+
the api is designed to be so simple you don't even need to know what a
|
34
|
+
state machine is :)
|
35
|
+
|
36
|
+
Some brief, high-level features include:
|
37
|
+
* Defining state machines on any Ruby class
|
38
|
+
* Multiple state machines on a single class
|
39
|
+
* before/after transition hooks with explicit transition requirements
|
40
|
+
* ActiveRecord integration
|
41
|
+
* DataMapper integration
|
42
|
+
* Sequel integration
|
43
|
+
* States of any data type
|
44
|
+
* State predicates
|
45
|
+
* GraphViz visualization creator
|
46
|
+
|
47
|
+
Examples of the usage patterns for some of the above features are shown below.
|
48
|
+
You can find more detailed documentation in the actual API.
|
36
49
|
|
37
50
|
== Usage
|
38
51
|
|
@@ -43,12 +56,16 @@ Below is an example of many of the features offered by this plugin, including
|
|
43
56
|
* Transition callbacks
|
44
57
|
* Conditional transitions
|
45
58
|
|
46
|
-
class Vehicle
|
59
|
+
class Vehicle
|
60
|
+
attr_accessor :seatbelt_on
|
61
|
+
|
47
62
|
state_machine :state, :initial => 'parked' do
|
48
63
|
before_transition :from => %w(parked idling), :do => :put_on_seatbelt
|
49
|
-
after_transition :
|
50
|
-
after_transition :on => '
|
51
|
-
after_transition :
|
64
|
+
after_transition :on => 'crash', :do => :tow
|
65
|
+
after_transition :on => 'repair', :do => :fix
|
66
|
+
after_transition :to => 'parked' do |vehicle, transition|
|
67
|
+
vehicle.seatbelt_on = false
|
68
|
+
end
|
52
69
|
|
53
70
|
event :park do
|
54
71
|
transition :to => 'parked', :from => %w(idling first_gear)
|
@@ -83,44 +100,112 @@ Below is an example of many of the features offered by this plugin, including
|
|
83
100
|
end
|
84
101
|
end
|
85
102
|
|
86
|
-
def
|
87
|
-
|
103
|
+
def initialize
|
104
|
+
@seatbelt_on = false
|
88
105
|
end
|
89
106
|
|
90
|
-
def
|
91
|
-
|
107
|
+
def put_on_seatbelt
|
108
|
+
@seatbelt_on = true
|
92
109
|
end
|
93
110
|
|
94
111
|
def auto_shop_busy?
|
95
112
|
false
|
96
113
|
end
|
114
|
+
|
115
|
+
def tow
|
116
|
+
# tow the vehicle
|
117
|
+
end
|
118
|
+
|
119
|
+
def fix
|
120
|
+
# get the vehicle fixed by a mechanic
|
121
|
+
end
|
97
122
|
end
|
98
123
|
|
99
|
-
Using the above
|
124
|
+
Using the above class as an example, you can interact with the state machine
|
100
125
|
like so:
|
101
126
|
|
102
|
-
vehicle = Vehicle.
|
103
|
-
vehicle.
|
104
|
-
vehicle
|
105
|
-
vehicle.
|
106
|
-
vehicle
|
107
|
-
vehicle.
|
108
|
-
vehicle
|
127
|
+
vehicle = Vehicle.new # => #<Vehicle:0xb7cf4eac @state="parked", @seatbelt_on=false>
|
128
|
+
vehicle.parked? # => true
|
129
|
+
vehicle.can_ignite? # => true
|
130
|
+
vehicle.next_ignite_transition # => #<StateMachine::Transition:0xb7c34cec ...>
|
131
|
+
vehicle.ignite # => true
|
132
|
+
vehicle.parked? # => false
|
133
|
+
vehicle.idling? # => true
|
134
|
+
vehicle # => #<Vehicle:0xb7cf4eac @state="idling", @seatbelt_on=true>
|
135
|
+
vehicle.shift_up # => true
|
136
|
+
vehicle # => #<Vehicle:0xb7cf4eac @state="first_gear", @seatbelt_on=true>
|
137
|
+
vehicle.shift_up # => true
|
138
|
+
vehicle # => #<Vehicle:0xb7cf4eac @state="second_gear", @seatbelt_on=true>
|
109
139
|
|
110
140
|
# The bang (!) operator can raise exceptions if the event fails
|
111
|
-
vehicle.park!
|
141
|
+
vehicle.park! # => StateMachine::InvalidTransition: Cannot transition via :park from "second_gear"
|
142
|
+
|
143
|
+
# Generic state predicates can raise exceptions if the value does not exist
|
144
|
+
vehicle.state?('parked') # => true
|
145
|
+
vehicle.state?('invalid') # => ArgumentError: "parked" is not a known state value
|
146
|
+
|
147
|
+
== Integrations
|
148
|
+
|
149
|
+
In addition to being able to define state machines on all Ruby classes, a set of
|
150
|
+
out-of-the-box integrations are available for some of the more popular Ruby
|
151
|
+
libraries. These integrations add library-specific behavior, allowing for state
|
152
|
+
machines to work more tightly with the conventions defined by those libraries.
|
153
|
+
|
154
|
+
The integrations currently available include:
|
155
|
+
* ActiveRecord models
|
156
|
+
* DataMapper resources
|
157
|
+
* Sequel models
|
158
|
+
|
159
|
+
A brief overview of these integrations is described below.
|
160
|
+
|
161
|
+
=== ActiveRecord
|
162
|
+
|
163
|
+
The ActiveRecord integration adds support for database transactions, automatically
|
164
|
+
saving the record, named scopes, and observers. For example,
|
165
|
+
|
166
|
+
class Vehicle < ActiveRecord::Base
|
167
|
+
state_machine :initial => 'parked' do
|
168
|
+
before_transition :to => 'idling', :do => :put_on_seatbelt
|
169
|
+
after_transition :to => 'parked' do |vehicle, transition|
|
170
|
+
vehicle.seatbelt = 'off'
|
171
|
+
end
|
172
|
+
|
173
|
+
event :ignite do
|
174
|
+
transition :to => 'idling', :from => 'parked'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def put_on_seatbelt
|
179
|
+
...
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class VehicleObserver < ActiveRecord::Observer
|
184
|
+
# Callback for :ignite event *before* the transition is performed
|
185
|
+
def before_ignite(vehicle, transition)
|
186
|
+
# log message
|
187
|
+
end
|
188
|
+
|
189
|
+
# Generic transition callback *before* the transition is performed
|
190
|
+
def after_transition(vehicle, transition)
|
191
|
+
Audit.log(vehicle, transition)
|
192
|
+
end
|
193
|
+
end
|
112
194
|
|
113
|
-
|
195
|
+
For more information about the various behaviors added for ActiveRecord state
|
196
|
+
machines, see StateMachine::Integrations::ActiveRecord.
|
197
|
+
|
198
|
+
==== With enumerations
|
114
199
|
|
115
200
|
Using the acts_as_enumeration[http://github.com/pluginaweek/acts_as_enumeration] plugin
|
116
|
-
states can be transparently stored using
|
201
|
+
with an ActiveRecord integration, states can be transparently stored using
|
202
|
+
record ids in the database like so:
|
117
203
|
|
118
204
|
class VehicleState < ActiveRecord::Base
|
119
205
|
acts_as_enumeration
|
120
206
|
|
121
207
|
create :id => 1, :name => 'parked'
|
122
208
|
create :id => 2, :name => 'idling'
|
123
|
-
create :id => 3, :name => 'first_gear'
|
124
209
|
...
|
125
210
|
end
|
126
211
|
|
@@ -133,31 +218,151 @@ states can be transparently stored using record ids in the database like so:
|
|
133
218
|
event :park do
|
134
219
|
transition :to => 'parked', :from => %w(idling first_gear)
|
135
220
|
end
|
136
|
-
|
137
|
-
event :ignite do
|
138
|
-
transition :to => 'stalled', :from => 'stalled'
|
139
|
-
transition :to => 'idling', :from => 'parked'
|
140
|
-
end
|
141
221
|
end
|
142
222
|
|
143
223
|
...
|
144
224
|
end
|
145
225
|
|
146
|
-
Notice
|
147
|
-
|
148
|
-
|
226
|
+
Notice that the state machine definition remains *exactly* the same. However,
|
227
|
+
when interacting with the records, the actual state will be stored using the
|
228
|
+
identifiers defined for the enumeration:
|
149
229
|
|
150
230
|
vehicle = Vehicle.create # => #<Vehicle id: 1, seatbelt_on: false, state_id: 1>
|
151
231
|
vehicle.ignite # => true
|
152
232
|
vehicle # => #<Vehicle id: 1, seatbelt_on: true, state_id: 2>
|
153
|
-
vehicle.shift_up # => true
|
154
|
-
vehicle # => #<Vehicle id: 1, seatbelt_on: true, state_id: 3>
|
155
233
|
|
156
234
|
This allows states to take on more complex functionality other than just being
|
157
235
|
a string value.
|
158
236
|
|
237
|
+
=== DataMapper
|
238
|
+
|
239
|
+
Like the ActiveRecord integration, the DataMapper integration adds support for
|
240
|
+
database transactions, automatically saving the record, named scopes, Extlib-like
|
241
|
+
callbacks, and observers. For example,
|
242
|
+
|
243
|
+
class Vehicle
|
244
|
+
include DataMapper::Resource
|
245
|
+
|
246
|
+
property :id, Serial
|
247
|
+
property :state, String
|
248
|
+
|
249
|
+
state_machine :initial => 'parked' do
|
250
|
+
before_transition :to => 'idling', :do => :put_on_seatbelt
|
251
|
+
after_transition :to => 'parked' do |transition|
|
252
|
+
self.seatbelt = 'off' # self is the record
|
253
|
+
end
|
254
|
+
|
255
|
+
event :ignite do
|
256
|
+
transition :to => 'idling', :from => 'parked'
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def put_on_seatbelt
|
261
|
+
...
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
class VehicleObserver
|
266
|
+
include DataMapper::Observer
|
267
|
+
|
268
|
+
observe Vehicle
|
269
|
+
|
270
|
+
# Callback for :ignite event *before* the transition is performed
|
271
|
+
before_transition :on => :ignite do |transition|
|
272
|
+
# log message (self is the record)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Generic transition callback *before* the transition is performed
|
276
|
+
after_transition do |transition, saved|
|
277
|
+
Audit.log(self, transition) if saved # self is the record
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
For more information about the various behaviors added for DataMapper state
|
282
|
+
machines, see StateMachine::Integrations::DataMapper.
|
283
|
+
|
284
|
+
=== Sequel
|
285
|
+
|
286
|
+
Like the ActiveRecord integration, the Sequel integration adds support for
|
287
|
+
database transactions, automatically saving the record, named scopes, and
|
288
|
+
callbacks. For example,
|
289
|
+
|
290
|
+
class Vehicle < Sequel::Model
|
291
|
+
state_machine :initial => 'parked' do
|
292
|
+
before_transition :to => 'idling', :do => :put_on_seatbelt
|
293
|
+
after_transition :to => 'parked' do |transition|
|
294
|
+
self.seatbelt = 'off' # self is the record
|
295
|
+
end
|
296
|
+
|
297
|
+
event :ignite do
|
298
|
+
transition :to => 'idling', :from => 'parked'
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def put_on_seatbelt
|
303
|
+
...
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
For more information about the various behaviors added for Sequel state
|
308
|
+
machines, see StateMachine::Integrations::Sequel.
|
309
|
+
|
159
310
|
== Tools
|
160
311
|
|
312
|
+
=== Generating graphs
|
313
|
+
|
314
|
+
This library comes with built-in support for generating di-graphs based on the
|
315
|
+
events, states, and transitions defined for a state machine using GraphViz[http://www.graphviz.org].
|
316
|
+
This requires that both the <tt>ruby-graphviz</tt> gem and graphviz library be
|
317
|
+
installed on the system.
|
318
|
+
|
319
|
+
==== Examples
|
320
|
+
|
321
|
+
To generate a graph for a specific file / class:
|
322
|
+
|
323
|
+
rake state_machine:draw FILE=vehicle.rb CLASS=Vehicle
|
324
|
+
|
325
|
+
To save files to a specific path:
|
326
|
+
|
327
|
+
rake state_machine:draw FILE=vehicle.rb CLASS=Vehicle TARGET=files
|
328
|
+
|
329
|
+
To customize the image format:
|
330
|
+
|
331
|
+
rake state_machine:draw FILE=vehicle.rb CLASS=Vehicle FORMAT=jpg
|
332
|
+
|
333
|
+
To generate multiple state machine graphs:
|
334
|
+
|
335
|
+
rake state_machine:draw FILE=vehicle.rb,car.rb CLASS=Vehicle,Car
|
336
|
+
|
337
|
+
*Note* that this will generate a different file for every state machine defined
|
338
|
+
in the class. The generates files will an output filename of the format #{class_name}_#{attribute}.#{format}.
|
339
|
+
|
340
|
+
For examples of actual images generated using this task, see those under the
|
341
|
+
test/examples folder.
|
342
|
+
|
343
|
+
==== Ruby on Rails Integration
|
344
|
+
|
345
|
+
There is a special integration Rake task for generating state machines for
|
346
|
+
classes used in a Ruby on Rails application. This task will load the application
|
347
|
+
environment, meaning that it's unnecessary to specify the actual file to load.
|
348
|
+
|
349
|
+
For example,
|
350
|
+
|
351
|
+
rake state_machine:draw:rails CLASS=Vehicle
|
352
|
+
|
353
|
+
==== Merb Integration
|
354
|
+
|
355
|
+
Like Ruby on Rails, there is a special integration Rake task for generating
|
356
|
+
state machines for classes used in a Merb application. This task will load the
|
357
|
+
application environment, meaning that it's unnecessary to specify the actual
|
358
|
+
files to load.
|
359
|
+
|
360
|
+
For example,
|
361
|
+
|
362
|
+
rake state_machine:draw:merb CLASS=Vehicle
|
363
|
+
|
364
|
+
=== Interactive graphs
|
365
|
+
|
161
366
|
Jean Bovet - {Visual Automata Simulator}[http://www.cs.usfca.edu/~jbovet/vas.html].
|
162
367
|
This is a great tool for "simulating, visualizing and transforming finite state
|
163
368
|
automata and Turing Machines". This tool can help in the creation of states and
|
@@ -165,16 +370,19 @@ events for your models. It is cross-platform, written in Java.
|
|
165
370
|
|
166
371
|
== Testing
|
167
372
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
To run against a specific version of Rails:
|
373
|
+
To run the entire test suite (will test ActiveRecord, DataMapper, and Sequel
|
374
|
+
integrations if available):
|
172
375
|
|
173
|
-
rake test
|
376
|
+
rake test
|
174
377
|
|
175
378
|
== Dependencies
|
176
379
|
|
177
|
-
|
380
|
+
By default, there are no dependencies. If using specific integrations, those
|
381
|
+
dependencies are listed below.
|
382
|
+
|
383
|
+
* ActiveRecord[http://rubyonrails.org] integration: 2.1.0 or later
|
384
|
+
* DataMapper[http://datamapper.org] integration: 0.9.0 or later
|
385
|
+
* Sequel[http://sequel.rubyforge.org] integration: 2.8.0 or later
|
178
386
|
|
179
387
|
== References
|
180
388
|
|
data/Rakefile
CHANGED
@@ -5,11 +5,11 @@ require 'rake/contrib/sshpublisher'
|
|
5
5
|
|
6
6
|
spec = Gem::Specification.new do |s|
|
7
7
|
s.name = 'state_machine'
|
8
|
-
s.version = '0.
|
8
|
+
s.version = '0.4.0'
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
|
-
s.summary = 'Adds support for creating state machines for attributes
|
10
|
+
s.summary = 'Adds support for creating state machines for attributes on any Ruby class'
|
11
11
|
|
12
|
-
s.files = FileList['{lib,test}/**/*'] + %w(CHANGELOG.rdoc init.rb LICENSE Rakefile README.rdoc) - FileList['test/app_root/{log,log/*,script,script/*}']
|
12
|
+
s.files = FileList['{examples,lib,test}/**/*'] + %w(CHANGELOG.rdoc init.rb LICENSE Rakefile README.rdoc) - FileList['test/app_root/{log,log/*,script,script/*}']
|
13
13
|
s.require_path = 'lib'
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.test_files = Dir['test/**/*_test.rb']
|
@@ -86,3 +86,29 @@ task :release => [:gem, :package] do
|
|
86
86
|
ruby_forge.add_release(spec.rubyforge_project, spec.name, spec.version, file)
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
namespace :state_machine do
|
91
|
+
desc 'Draws a set of state machines using GraphViz. Target files to load with FILE=x,y,z; Machine class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x'
|
92
|
+
task :draw do
|
93
|
+
# Load the library
|
94
|
+
$:.unshift(File.dirname(__FILE__) + '/lib')
|
95
|
+
require 'state_machine'
|
96
|
+
|
97
|
+
# Build drawing options
|
98
|
+
options = {}
|
99
|
+
options[:file] = ENV['FILE'] if ENV['FILE']
|
100
|
+
options[:path] = ENV['TARGET'] if ENV['TARGET']
|
101
|
+
options[:format] = ENV['FORMAT'] if ENV['FORMAT']
|
102
|
+
options[:font] = ENV['FONT'] if ENV['FONT']
|
103
|
+
|
104
|
+
StateMachine::Machine.draw(ENV['CLASS'], options)
|
105
|
+
end
|
106
|
+
|
107
|
+
namespace :draw do
|
108
|
+
desc 'Draws a set of state machines using GraphViz for a Ruby on Rails application. Target class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x'
|
109
|
+
task :rails => [:environment, 'state_machine:draw']
|
110
|
+
|
111
|
+
desc 'Draws a set of state machines using GraphViz for a Merb application. Target class with CLASS=x,y,z; Font name with FONT=x; Image format with FORMAT=x'
|
112
|
+
task :merb => [:merb_env, 'state_machine:draw']
|
113
|
+
end
|
114
|
+
end
|