state_machine 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGELOG.rdoc +17 -0
  2. data/LICENSE +1 -1
  3. data/README.rdoc +54 -84
  4. data/Rakefile +1 -1
  5. data/examples/Car_state.png +0 -0
  6. data/examples/Vehicle_state.png +0 -0
  7. data/examples/auto_shop.rb +11 -0
  8. data/examples/car.rb +19 -0
  9. data/examples/traffic_light.rb +9 -0
  10. data/examples/vehicle.rb +35 -0
  11. data/lib/state_machine.rb +65 -52
  12. data/lib/state_machine/assertions.rb +1 -1
  13. data/lib/state_machine/callback.rb +13 -9
  14. data/lib/state_machine/eval_helpers.rb +4 -3
  15. data/lib/state_machine/event.rb +51 -33
  16. data/lib/state_machine/extensions.rb +2 -2
  17. data/lib/state_machine/guard.rb +47 -41
  18. data/lib/state_machine/integrations.rb +67 -0
  19. data/lib/state_machine/integrations/active_record.rb +62 -36
  20. data/lib/state_machine/integrations/active_record/observer.rb +41 -0
  21. data/lib/state_machine/integrations/data_mapper.rb +23 -37
  22. data/lib/state_machine/integrations/data_mapper/observer.rb +23 -9
  23. data/lib/state_machine/integrations/sequel.rb +23 -24
  24. data/lib/state_machine/machine.rb +380 -277
  25. data/lib/state_machine/node_collection.rb +142 -0
  26. data/lib/state_machine/state.rb +114 -69
  27. data/lib/state_machine/state_collection.rb +38 -0
  28. data/lib/state_machine/transition.rb +36 -17
  29. data/test/active_record.log +2940 -85664
  30. data/test/functional/state_machine_test.rb +49 -53
  31. data/test/sequel.log +747 -11990
  32. data/test/unit/assertions_test.rb +2 -1
  33. data/test/unit/callback_test.rb +14 -12
  34. data/test/unit/eval_helpers_test.rb +25 -6
  35. data/test/unit/event_test.rb +144 -124
  36. data/test/unit/guard_test.rb +118 -140
  37. data/test/unit/integrations/active_record_test.rb +102 -68
  38. data/test/unit/integrations/data_mapper_test.rb +48 -37
  39. data/test/unit/integrations/sequel_test.rb +34 -25
  40. data/test/unit/integrations_test.rb +42 -0
  41. data/test/unit/machine_test.rb +460 -531
  42. data/test/unit/node_collection_test.rb +208 -0
  43. data/test/unit/state_collection_test.rb +167 -0
  44. data/test/unit/state_machine_test.rb +1 -1
  45. data/test/unit/state_test.rb +223 -200
  46. data/test/unit/transition_test.rb +81 -46
  47. metadata +17 -3
  48. data/test/data_mapper.log +0 -30860
@@ -1,5 +1,22 @@
1
1
  == master
2
2
 
3
+ == 0.5.0 / 2008-01-11
4
+
5
+ * Add to_name and from_name to transition objects
6
+ * Add nicely formatted #inspect for transitions
7
+ * Fix ActiveRecord integrations failing when the database doesn't exist yet
8
+ * Fix states not being drawn in GraphViz graphs in the correct order
9
+ * Add nicely formatted #inspect for states and events
10
+ * Simplify machine context-switching
11
+ * Store events/states in enumerable node collections
12
+ * No longer allow subclasses to change the integration
13
+ * Move fire! action logic into the Event class (no longer calls fire action on the object)
14
+ * Allow states in subclasses to have different values
15
+ * Recommend that all states be referenced as symbols instead of strings
16
+ * All states must now be named (and can be associated with other value types)
17
+ * Add support for customizing the actual stored value for a state
18
+ * Add compatibility with Ruby 1.9+
19
+
3
20
  == 0.4.3 / 2008-12-28
4
21
 
5
22
  * Allow dm-observer integration to be optional
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2006-2008 Aaron Pfefier
1
+ Copyright (c) 2006-2009 Aaron Pfefier
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -24,7 +24,7 @@ Source
24
24
  == Description
25
25
 
26
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
27
+ the state of an object is kept by creating multiple boolean attributes and
28
28
  deciding how to behave based on the values. This can become cumbersome and
29
29
  difficult to maintain when the complexity of your class starts to increase.
30
30
 
@@ -41,13 +41,15 @@ Some brief, high-level features include:
41
41
  * ActiveRecord integration
42
42
  * DataMapper integration
43
43
  * Sequel integration
44
- * States of any data type
45
44
  * State predicates
46
45
  * State-driven behavior
46
+ * State values of any data type
47
+ * Dynamically-generated state values
48
+ * Inheritance
47
49
  * GraphViz visualization creator
48
50
 
49
51
  Examples of the usage patterns for some of the above features are shown below.
50
- You can find more detailed documentation in the actual API.
52
+ You can find much more detailed documentation in the actual API.
51
53
 
52
54
  == Usage
53
55
 
@@ -59,79 +61,83 @@ Below is an example of many of the features offered by this plugin, including:
59
61
  * Transition callbacks
60
62
  * Conditional transitions
61
63
  * State-driven behavior
64
+ * Customized state values
62
65
 
63
66
  Class definition:
64
67
 
65
68
  class Vehicle
66
69
  attr_accessor :seatbelt_on
67
70
 
68
- state_machine :state, :initial => 'parked' do
69
- before_transition :from => %w(parked idling), :do => :put_on_seatbelt
70
- after_transition :on => 'crash', :do => :tow
71
- after_transition :on => 'repair', :do => :fix
72
- after_transition :to => 'parked' do |vehicle, transition|
71
+ state_machine :state, :initial => :parked do
72
+ before_transition :from => [:parked, :idling], :do => :put_on_seatbelt
73
+ after_transition :on => :crash, :do => :tow
74
+ after_transition :on => :repair, :do => :fix
75
+ after_transition :to => :parked do |vehicle, transition|
73
76
  vehicle.seatbelt_on = false
74
77
  end
75
78
 
76
79
  event :park do
77
- transition :to => 'parked', :from => %w(idling first_gear)
80
+ transition :to => :parked, :from => [:idling, :first_gear]
78
81
  end
79
82
 
80
83
  event :ignite do
81
- transition :to => 'stalled', :from => 'stalled'
82
- transition :to => 'idling', :from => 'parked'
84
+ transition :to => :stalled, :from => :stalled
85
+ transition :to => :idling, :from => :parked
83
86
  end
84
87
 
85
88
  event :idle do
86
- transition :to => 'idling', :from => 'first_gear'
89
+ transition :to => :idling, :from => :first_gear
87
90
  end
88
91
 
89
92
  event :shift_up do
90
- transition :to => 'first_gear', :from => 'idling'
91
- transition :to => 'second_gear', :from => 'first_gear'
92
- transition :to => 'third_gear', :from => 'second_gear'
93
+ transition :to => :first_gear, :from => :idling
94
+ transition :to => :second_gear, :from => :first_gear
95
+ transition :to => :third_gear, :from => :second_gear
93
96
  end
94
97
 
95
98
  event :shift_down do
96
- transition :to => 'second_gear', :from => 'third_gear'
97
- transition :to => 'first_gear', :from => 'second_gear'
99
+ transition :to => :second_gear, :from => :third_gear
100
+ transition :to => :first_gear, :from => :second_gear
98
101
  end
99
102
 
100
103
  event :crash do
101
- transition :to => 'stalled', :from => %w(first_gear second_gear third_gear), :unless => :auto_shop_busy?
104
+ transition :to => :stalled, :from => [:first_gear, :second_gear, :third_gear], :unless => :auto_shop_busy?
102
105
  end
103
106
 
104
107
  event :repair do
105
- transition :to => 'parked', :from => 'stalled', :if => :auto_shop_busy?
108
+ transition :to => :parked, :from => :stalled, :if => :auto_shop_busy?
106
109
  end
107
110
 
108
- state 'parked' do
111
+ state :parked do
109
112
  def speed
110
113
  0
111
114
  end
112
115
  end
113
116
 
114
- state 'idling', 'first_gear' do
117
+ state :idling, :first_gear do
115
118
  def speed
116
119
  10
117
120
  end
118
121
  end
119
122
 
120
- state 'second_gear' do
123
+ state :second_gear do
121
124
  def speed
122
125
  20
123
126
  end
124
127
  end
125
128
  end
126
129
 
127
- state_machine :hood_state, :initial => 'closed', :namespace => 'hood' do
130
+ state_machine :hood_state, :initial => :closed, :namespace => 'hood' do
128
131
  event :open do
129
- transition :to => 'opened', :from => 'closed'
132
+ transition :to => :opened
130
133
  end
131
134
 
132
135
  event :close do
133
- transition :to => 'closed', :from => 'opened'
136
+ transition :to => :closed
134
137
  end
138
+
139
+ state :opened, :value => 1
140
+ state :closed, :value => 0
135
141
  end
136
142
 
137
143
  def initialize
@@ -160,9 +166,11 @@ Using the above class as an example, you can interact with the state machine
160
166
  like so:
161
167
 
162
168
  vehicle = Vehicle.new # => #<Vehicle:0xb7cf4eac @state="parked", @seatbelt_on=false>
169
+ vehicle.state # => "parked"
170
+ vehicle.state_name # => :parked
163
171
  vehicle.parked? # => true
164
172
  vehicle.can_ignite? # => true
165
- vehicle.next_ignite_transition # => #<StateMachine::Transition:0xb7c34cec ...>
173
+ vehicle.next_ignite_transition # => #<StateMachine::Transition attribute=:state event=:ignite from="parked" from_name=:parked to="idling" to_name=:idling>
166
174
  vehicle.speed # => 0
167
175
 
168
176
  vehicle.ignite # => true
@@ -180,15 +188,20 @@ like so:
180
188
  vehicle # => #<Vehicle:0xb7cf4eac @state="second_gear", @seatbelt_on=true>
181
189
 
182
190
  # The bang (!) operator can raise exceptions if the event fails
183
- vehicle.park! # => StateMachine::InvalidTransition: Cannot transition via :park from "second_gear"
191
+ vehicle.park! # => StateMachine::InvalidTransition: Cannot transition state via :park from :second_gear
184
192
 
185
193
  # Generic state predicates can raise exceptions if the value does not exist
186
- vehicle.state?('parked') # => true
187
- vehicle.state?('invalid') # => ArgumentError: "parked" is not a known state value
194
+ vehicle.state?(:parked) # => true
195
+ vehicle.state?(:invalid) # => ArgumentError: :invalid is an invalid name
188
196
 
189
197
  # Namespaced machines have uniquely-generated methods
198
+ vehicle.hood_state # => 0
199
+ vehicle.hood_state_name # => :closed
200
+
190
201
  vehicle.can_open_hood? # => true
191
202
  vehicle.open_hood # => true
203
+ vehicle.hood_state # => 1
204
+ vehicle.hood_state_name # => :opened
192
205
  vehicle.can_close_hood? # => true
193
206
 
194
207
  vehicle.hood_opened? # => true
@@ -218,14 +231,14 @@ The ActiveRecord integration adds support for database transactions, automatical
218
231
  saving the record, named scopes, and observers. For example,
219
232
 
220
233
  class Vehicle < ActiveRecord::Base
221
- state_machine :initial => 'parked' do
222
- before_transition :to => 'idling', :do => :put_on_seatbelt
223
- after_transition :to => 'parked' do |vehicle, transition|
234
+ state_machine :initial => :parked do
235
+ before_transition :to => :idling, :do => :put_on_seatbelt
236
+ after_transition :to => :parked do |vehicle, transition|
224
237
  vehicle.seatbelt = 'off'
225
238
  end
226
239
 
227
240
  event :ignite do
228
- transition :to => 'idling', :from => 'parked'
241
+ transition :to => :idling, :from => :parked
229
242
  end
230
243
  end
231
244
 
@@ -249,45 +262,6 @@ saving the record, named scopes, and observers. For example,
249
262
  For more information about the various behaviors added for ActiveRecord state
250
263
  machines, see StateMachine::Integrations::ActiveRecord.
251
264
 
252
- ==== With enumerations
253
-
254
- Using the acts_as_enumeration[http://github.com/pluginaweek/acts_as_enumeration] plugin
255
- with an ActiveRecord integration, states can be transparently stored using
256
- record ids in the database like so:
257
-
258
- class VehicleState < ActiveRecord::Base
259
- acts_as_enumeration
260
-
261
- create :id => 1, :name => 'parked'
262
- create :id => 2, :name => 'idling'
263
- ...
264
- end
265
-
266
- class Vehicle < ActiveRecord::Base
267
- belongs_to :state, :class_name => 'VehicleState'
268
-
269
- state_machine :state, :initial => 'parked' do
270
- ...
271
-
272
- event :park do
273
- transition :to => 'parked', :from => %w(idling first_gear)
274
- end
275
- end
276
-
277
- ...
278
- end
279
-
280
- Notice that the state machine definition remains *exactly* the same. However,
281
- when interacting with the records, the actual state will be stored using the
282
- identifiers defined for the enumeration:
283
-
284
- vehicle = Vehicle.create # => #<Vehicle id: 1, seatbelt_on: false, state_id: 1>
285
- vehicle.ignite # => true
286
- vehicle # => #<Vehicle id: 1, seatbelt_on: true, state_id: 2>
287
-
288
- This allows states to take on more complex functionality other than just being
289
- a string value.
290
-
291
265
  === DataMapper
292
266
 
293
267
  Like the ActiveRecord integration, the DataMapper integration adds support for
@@ -300,14 +274,14 @@ callbacks, and observers. For example,
300
274
  property :id, Serial
301
275
  property :state, String
302
276
 
303
- state_machine :initial => 'parked' do
304
- before_transition :to => 'idling', :do => :put_on_seatbelt
305
- after_transition :to => 'parked' do |transition|
277
+ state_machine :initial => :parked do
278
+ before_transition :to => :idling, :do => :put_on_seatbelt
279
+ after_transition :to => :parked do |transition|
306
280
  self.seatbelt = 'off' # self is the record
307
281
  end
308
282
 
309
283
  event :ignite do
310
- transition :to => 'idling', :from => 'parked'
284
+ transition :to => :idling, :from => :parked
311
285
  end
312
286
  end
313
287
 
@@ -345,14 +319,14 @@ database transactions, automatically saving the record, named scopes, and
345
319
  callbacks. For example,
346
320
 
347
321
  class Vehicle < Sequel::Model
348
- state_machine :initial => 'parked' do
349
- before_transition :to => 'idling', :do => :put_on_seatbelt
350
- after_transition :to => 'parked' do |transition|
322
+ state_machine :initial => :parked do
323
+ before_transition :to => :idling, :do => :put_on_seatbelt
324
+ after_transition :to => :parked do |transition|
351
325
  self.seatbelt = 'off' # self is the record
352
326
  end
353
327
 
354
328
  event :ignite do
355
- transition :to => 'idling', :from => 'parked'
329
+ transition :to => :idling, :from => :parked
356
330
  end
357
331
  end
358
332
 
@@ -441,7 +415,3 @@ dependencies are listed below.
441
415
  * ActiveRecord[http://rubyonrails.org] integration: 2.1.0 or later
442
416
  * DataMapper[http://datamapper.org] integration: 0.9.0 or later
443
417
  * Sequel[http://sequel.rubyforge.org] integration: 2.8.0 or later
444
-
445
- == References
446
-
447
- * acts_as_enumeration[http://github.com/pluginaweek/acts_as_enumeration]
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/contrib/sshpublisher'
5
5
 
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = 'state_machine'
8
- s.version = '0.4.3'
8
+ s.version = '0.5.0'
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.summary = 'Adds support for creating state machines for attributes on any Ruby class'
11
11
 
Binary file
Binary file
@@ -0,0 +1,11 @@
1
+ class AutoShop
2
+ state_machine :initial => :available do
3
+ event :tow_vehicle do
4
+ transition :to => :busy, :from => :available
5
+ end
6
+
7
+ event :fix_vehicle do
8
+ transition :to => :available, :from => :busy
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ class Car < Vehicle
2
+ state_machine do
3
+ event :reverse do
4
+ transition :to => :backing_up, :from => [:parked, :idling, :first_gear]
5
+ end
6
+
7
+ event :park do
8
+ transition :to => :parked, :from => :backing_up
9
+ end
10
+
11
+ event :idle do
12
+ transition :to => :idling, :from => :backing_up
13
+ end
14
+
15
+ event :shift_up do
16
+ transition :to => :first_gear, :from => :backing_up
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ class TrafficLight
2
+ state_machine :initial => :stop do
3
+ event :cycle do
4
+ transition :to => :proceed, :from => :stop
5
+ transition :to => :caution, :from => :proceed
6
+ transition :to => :stop, :from => :caution
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ class Vehicle
2
+ state_machine :initial => :parked do
3
+ event :park do
4
+ transition :to => :parked, :from => [:idling, :first_gear]
5
+ end
6
+
7
+ event :ignite do
8
+ transition :to => :stalled, :from => :stalled
9
+ transition :to => :idling, :from => :parked
10
+ end
11
+
12
+ event :idle do
13
+ transition :to => :idling, :from => :first_gear
14
+ end
15
+
16
+ event :shift_up do
17
+ transition :to => :first_gear, :from => :idling
18
+ transition :to => :second_gear, :from => :first_gear
19
+ transition :to => :third_gear, :from => :second_gear
20
+ end
21
+
22
+ event :shift_down do
23
+ transition :to => :second_gear, :from => :third_gear
24
+ transition :to => :first_gear, :from => :second_gear
25
+ end
26
+
27
+ event :crash do
28
+ transition :to => :stalled, :from => [:first_gear, :second_gear, :third_gear]
29
+ end
30
+
31
+ event :repair do
32
+ transition :to => :parked, :from => :stalled
33
+ end
34
+ end
35
+ end
@@ -6,16 +6,27 @@ require 'state_machine/machine'
6
6
  module StateMachine
7
7
  module MacroMethods
8
8
  # Creates a new state machine for the given attribute. The default
9
- # attribute, if not specified, is "state".
9
+ # attribute, if not specified, is <tt>:state</tt>.
10
10
  #
11
11
  # Configuration options:
12
- # * +initial+ - The initial value to set the attribute to. This can be a static value or a lambda block which will be evaluated at runtime. Default is nil.
13
- # * +action+ - The action to invoke when an object transitions. Default is nil unless otherwise specified by the configured integration.
14
- # * +plural+ - The pluralized name of the attribute. By default, this will attempt to call +pluralize+ on the attribute, otherwise an "s" is appended.
15
- # * +namespace+ - The name to use for namespacing all generated instance methods (e.g. "email" => "activate_email", "deactivate_email", etc.). Default is no namespace.
16
- # * +integration+ - The name of the integration to use for adding library-specific behavior to the machine. Built-in integrations include :data_mapper, :active_record, and :sequel. By default, this is determined automatically.
17
- #
18
- # This also requires a block which will be used to actually configure the
12
+ # * <tt>:initial</tt> - The initial state of the attribute. This can be a
13
+ # static state or a lambda block which will be evaluated at runtime
14
+ # (e.g. lambda {|vehicle| vehicle.speed == 0 ? :parked : :idling}).
15
+ # Default is nil.
16
+ # * <tt>:action</tt> - The action to invoke when an object transitions.
17
+ # Default is nil unless otherwise specified by the configured integration.
18
+ # * <tt>:plural</tt> - The pluralized name of the attribute. By default,
19
+ # this will attempt to call +pluralize+ on the attribute, otherwise
20
+ # an "s" is appended. This is used for generating scopes.
21
+ # * <tt>:namespace</tt> - The name to use for namespacing all generated
22
+ # instance methods (e.g. "heater" would generate :turn_on_heater and
23
+ # :turn_off_header for the :turn_on/:turn_off events). Default is nil.
24
+ # * <tt>:integration</tt> - The name of the integration to use for adding
25
+ # library-specific behavior to the machine. Built-in integrations include
26
+ # :data_mapper, :active_record, and :sequel. By default, this is
27
+ # determined automatically.
28
+ #
29
+ # This also expects a block which will be used to actually configure the
19
30
  # states, events and transitions for the state machine. *Note* that this
20
31
  # block will be executed within the context of the state machine. As a
21
32
  # result, you will not be able to access any class methods unless you refer
@@ -36,7 +47,7 @@ module StateMachine
36
47
  # end
37
48
  # end
38
49
  #
39
- # The above example will define a state machine for the attribute "state"
50
+ # The above example will define a state machine for the +state+ attribute
40
51
  # on the class. Every vehicle will start without an initial state.
41
52
  #
42
53
  # With a custom attribute:
@@ -50,15 +61,15 @@ module StateMachine
50
61
  # With a static initial state:
51
62
  #
52
63
  # class Vehicle
53
- # state_machine :status, :initial => 'Vehicle' do
64
+ # state_machine :status, :initial => :parked do
54
65
  # ...
55
66
  # end
56
67
  # end
57
68
  #
58
69
  # With a dynamic initial state:
59
70
  #
60
- # class Switch
61
- # state_machine :status, :initial => lambda {|switch| (8..22).include?(Time.now.hour) ? 'on' : 'off'} do
71
+ # class Vehicle
72
+ # state_machine :status, :initial => lambda {|vehicle| vehicle.speed == 0 ? :parked : :idling} do
62
73
  # ...
63
74
  # end
64
75
  # end
@@ -69,13 +80,15 @@ module StateMachine
69
80
  # of the machine. In order to access this value and modify it during
70
81
  # transitions, a reader/writer must be available. The following methods
71
82
  # will be automatically generated if they are not already defined
72
- # (assuming the attribute is called "state"):
83
+ # (assuming the attribute is called +state+):
73
84
  # * <tt>state</tt> - Gets the current value for the attribute
74
85
  # * <tt>state=(value)</tt> - Sets the current value for the attribute
75
- # * <tt>state?(value)</tt> - Checks the given value against the current value. If the value is not a known state, then an ArgumentError is raised.
86
+ # * <tt>state?(name)</tt> - Checks the given state name against the current
87
+ # state. If the name is not a known state, then an ArgumentError is raised.
88
+ # * <tt>state_name</tt> - Gets the name of the state for the current value
76
89
  #
77
- # For example, the following machine definition will not generate any
78
- # accessor methods since the class has already defined an attribute
90
+ # For example, the following machine definition will not generate the reader
91
+ # or writer methods since the class has already defined an attribute
79
92
  # accessor:
80
93
  #
81
94
  # class Vehicle
@@ -86,7 +99,7 @@ module StateMachine
86
99
  # end
87
100
  # end
88
101
  #
89
- # On the other hand, the following state machine will define both a
102
+ # On the other hand, the following state machine will define *both* a
90
103
  # reader and writer method, which is functionally equivalent to the
91
104
  # example above:
92
105
  #
@@ -106,13 +119,13 @@ module StateMachine
106
119
  # For example,
107
120
  #
108
121
  # class Vehicle
109
- # state_machine :state, :initial => 'parked' do
122
+ # state_machine :state, :initial => :parked do
110
123
  # ...
111
124
  # end
112
125
  # end
113
126
  #
114
- # v = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
115
- # v.state # => "parked"
127
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
128
+ # vehicle.state # => "parked"
116
129
  #
117
130
  # In the above example, no +initialize+ method is defined. As a result,
118
131
  # the default behavior of initializing the state machine attributes is used.
@@ -120,7 +133,7 @@ module StateMachine
120
133
  # In the following example, a custom +initialize+ method is defined:
121
134
  #
122
135
  # class Vehicle
123
- # state_machine :state, :initial => 'parked' do
136
+ # state_machine :state, :initial => :parked do
124
137
  # ...
125
138
  # end
126
139
  #
@@ -128,8 +141,8 @@ module StateMachine
128
141
  # end
129
142
  # end
130
143
  #
131
- # v = Vehicle.new # => #<Vehicle:0xb7c77678>
132
- # v.state # => nil
144
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c77678>
145
+ # vehicle.state # => nil
133
146
  #
134
147
  # Since the +initialize+ method is defined, the state machine attributes
135
148
  # never get initialized. In order to ensure that all initialization hooks
@@ -137,7 +150,7 @@ module StateMachine
137
150
  # like so:
138
151
  #
139
152
  # class Vehicle
140
- # state_machine :state, :initial => 'parked' do
153
+ # state_machine :state, :initial => :parked do
141
154
  # ...
142
155
  # end
143
156
  #
@@ -147,19 +160,19 @@ module StateMachine
147
160
  # end
148
161
  # end
149
162
  #
150
- # v = Vehicle.new # => #<Vehicle:0xb7c464b0 @state="parked">
151
- # v.state # => "parked"
163
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
164
+ # vehicle.state # => "parked"
152
165
  #
153
- # Because of the way the inclusion of modules works in Ruby, calling <tt>super()</tt>
154
- # will not only call the superclass's +initialize+, but also +initialize+ on
155
- # all included modules. This allows the original state machine hook to get
156
- # called properly.
166
+ # Because of the way the inclusion of modules works in Ruby, calling
167
+ # <tt>super()</tt> will not only call the superclass's +initialize+, but
168
+ # also +initialize+ on all included modules. This allows the original state
169
+ # machine hook to get called properly.
157
170
  #
158
171
  # If you want to avoid calling the superclass's constructor, but still want
159
172
  # to initialize the state machine attributes:
160
173
  #
161
174
  # class Vehicle
162
- # state_machine :state, :initial => 'parked' do
175
+ # state_machine :state, :initial => :parked do
163
176
  # ...
164
177
  # end
165
178
  #
@@ -169,24 +182,24 @@ module StateMachine
169
182
  # end
170
183
  # end
171
184
  #
172
- # v = Vehicle.new # => #<Vehicle:0xb7c464b0 @state="parked">
173
- # v.state # => "parked"
185
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
186
+ # vehicle.state # => "parked"
174
187
  #
175
188
  # == States
176
189
  #
177
190
  # All of the valid states for the machine are automatically tracked based
178
191
  # on the events, transitions, and callbacks defined for the machine. If
179
192
  # there are additional states that are never referenced, these should be
180
- # explicitly added using the StateMachine::Machine#other_states
181
- # helper.
193
+ # explicitly added using the StateMachine::Machine#state or
194
+ # StateMachine::Machine#other_states helpers.
182
195
  #
183
- # When using String or Symbol-based states, a predicate method for that
184
- # state is generated on the class. For example,
196
+ # When a new state is defined, a predicate method for that state is
197
+ # generated on the class. For example,
185
198
  #
186
199
  # class Vehicle
187
- # state_machine :initial => 'parked' do
200
+ # state_machine :initial => :parked do
188
201
  # event :ignite do
189
- # transition :to => 'idling'
202
+ # transition :to => :idling
190
203
  # end
191
204
  # end
192
205
  # end
@@ -227,23 +240,23 @@ module StateMachine
227
240
  # For example,
228
241
  #
229
242
  # class Vehicle
230
- # state_machine :heater_state, :initial => 'off' :namespace => 'heater' do
243
+ # state_machine :heater_state, :initial => :off :namespace => 'heater' do
231
244
  # event :turn_on do
232
- # transition :to => 'on', :from => 'off'
245
+ # transition :to => :on
233
246
  # end
234
247
  #
235
248
  # event :turn_off do
236
- # transition :to => 'off', :from => 'on'
249
+ # transition :to => :off
237
250
  # end
238
251
  # end
239
252
  #
240
- # state_machine :hood_state, :initial => 'closed', :namespace => 'hood' do
253
+ # state_machine :hood_state, :initial => :closed, :namespace => 'hood' do
241
254
  # event :open do
242
- # transition :to => 'opened', :from => 'closed'
255
+ # transition :to => :opened
243
256
  # end
244
257
  #
245
258
  # event :close do
246
- # transition :to => 'closed', :from => 'opened'
259
+ # transition :to => :closed
247
260
  # end
248
261
  # end
249
262
  # end
@@ -275,19 +288,19 @@ module StateMachine
275
288
  #
276
289
  # For integrations that support it, a group of default scope filters will
277
290
  # be automatically created for assisting in finding objects that have the
278
- # attribute set to a given value.
291
+ # attribute set to the value for a given set of states.
279
292
  #
280
293
  # For example,
281
294
  #
282
- # Vehicle.with_state('parked') # => Finds all vehicles where the state is parked
283
- # Vehicle.with_states('parked', 'idling') # => Finds all vehicles where the state is either parked or idling
295
+ # Vehicle.with_state(:parked) # => Finds all vehicles where the state is parked
296
+ # Vehicle.with_states(:parked, :idling) # => Finds all vehicles where the state is either parked or idling
284
297
  #
285
- # Vehicle.without_state('parked') # => Finds all vehicles where the state is *not* parked
286
- # Vehicle.without_states('parked', 'idling') # => Finds all vehicles where the state is *not* parked or idling
298
+ # Vehicle.without_state(:parked) # => Finds all vehicles where the state is *not* parked
299
+ # Vehicle.without_states(:parked, :idling) # => Finds all vehicles where the state is *not* parked or idling
287
300
  #
288
301
  # *Note* that if class methods already exist with those names (i.e.
289
- # "with_state", "with_states", "without_state", or "without_states"), then
290
- # a scope will not be defined for that name.
302
+ # :with_state, :with_states, :without_state, or :without_states), then a
303
+ # scope will not be defined for that name.
291
304
  #
292
305
  # See StateMachine::Machine for more information about using
293
306
  # integrations and the individual integration docs for information about