state_machine 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gitignore +11 -0
  2. data/.travis.yml +16 -0
  3. data/.yardopts +5 -0
  4. data/Appraisals +260 -0
  5. data/CHANGELOG.rdoc +15 -0
  6. data/Gemfile +3 -0
  7. data/README.rdoc +156 -29
  8. data/Rakefile +31 -57
  9. data/gemfiles/active_model-3.0.0.gemfile +7 -0
  10. data/gemfiles/active_model-3.0.0.gemfile.lock +32 -0
  11. data/gemfiles/active_model-3.0.5.gemfile +7 -0
  12. data/gemfiles/active_model-3.0.5.gemfile.lock +32 -0
  13. data/gemfiles/active_record-2.0.0.gemfile +8 -0
  14. data/gemfiles/active_record-2.0.0.gemfile.lock +30 -0
  15. data/gemfiles/active_record-2.0.5.gemfile +8 -0
  16. data/gemfiles/active_record-2.0.5.gemfile.lock +30 -0
  17. data/gemfiles/active_record-2.1.0.gemfile +8 -0
  18. data/gemfiles/active_record-2.1.0.gemfile.lock +30 -0
  19. data/gemfiles/active_record-2.1.2.gemfile +8 -0
  20. data/gemfiles/active_record-2.1.2.gemfile.lock +30 -0
  21. data/gemfiles/active_record-2.2.3.gemfile +8 -0
  22. data/gemfiles/active_record-2.2.3.gemfile.lock +30 -0
  23. data/gemfiles/active_record-2.3.12.gemfile +8 -0
  24. data/gemfiles/active_record-2.3.12.gemfile.lock +30 -0
  25. data/gemfiles/active_record-3.0.0.gemfile +8 -0
  26. data/gemfiles/active_record-3.0.0.gemfile.lock +44 -0
  27. data/gemfiles/active_record-3.0.5.gemfile +8 -0
  28. data/gemfiles/active_record-3.0.5.gemfile.lock +43 -0
  29. data/gemfiles/data_mapper-0.10.2.gemfile +12 -0
  30. data/gemfiles/data_mapper-0.10.2.gemfile.lock +45 -0
  31. data/gemfiles/data_mapper-0.9.11.gemfile +12 -0
  32. data/gemfiles/data_mapper-0.9.11.gemfile.lock +47 -0
  33. data/gemfiles/data_mapper-0.9.4.gemfile +12 -0
  34. data/gemfiles/data_mapper-0.9.4.gemfile.lock +61 -0
  35. data/gemfiles/data_mapper-0.9.7.gemfile +12 -0
  36. data/gemfiles/data_mapper-0.9.7.gemfile.lock +57 -0
  37. data/gemfiles/data_mapper-1.0.0.gemfile +12 -0
  38. data/gemfiles/data_mapper-1.0.0.gemfile.lock +53 -0
  39. data/gemfiles/data_mapper-1.0.1.gemfile +12 -0
  40. data/gemfiles/data_mapper-1.0.1.gemfile.lock +53 -0
  41. data/gemfiles/data_mapper-1.0.2.gemfile +12 -0
  42. data/gemfiles/data_mapper-1.0.2.gemfile.lock +53 -0
  43. data/gemfiles/data_mapper-1.1.0.gemfile +12 -0
  44. data/gemfiles/data_mapper-1.1.0.gemfile.lock +51 -0
  45. data/gemfiles/default.gemfile +7 -0
  46. data/gemfiles/default.gemfile.lock +24 -0
  47. data/gemfiles/mongo_mapper-0.5.5.gemfile +8 -0
  48. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +33 -0
  49. data/gemfiles/mongo_mapper-0.5.8.gemfile +8 -0
  50. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +33 -0
  51. data/gemfiles/mongo_mapper-0.6.0.gemfile +8 -0
  52. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +33 -0
  53. data/gemfiles/mongo_mapper-0.6.10.gemfile +8 -0
  54. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +33 -0
  55. data/gemfiles/mongo_mapper-0.7.0.gemfile +8 -0
  56. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +33 -0
  57. data/gemfiles/mongo_mapper-0.7.5.gemfile +8 -0
  58. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +36 -0
  59. data/gemfiles/mongo_mapper-0.8.0.gemfile +10 -0
  60. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +40 -0
  61. data/gemfiles/mongo_mapper-0.8.3.gemfile +10 -0
  62. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +40 -0
  63. data/gemfiles/mongo_mapper-0.8.4.gemfile +8 -0
  64. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +38 -0
  65. data/gemfiles/mongo_mapper-0.8.6.gemfile +8 -0
  66. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +38 -0
  67. data/gemfiles/mongo_mapper-0.9.0.gemfile +7 -0
  68. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +41 -0
  69. data/gemfiles/mongoid-2.0.0.gemfile +7 -0
  70. data/gemfiles/mongoid-2.0.0.gemfile.lock +42 -0
  71. data/gemfiles/mongoid-2.1.4.gemfile +7 -0
  72. data/gemfiles/mongoid-2.1.4.gemfile.lock +40 -0
  73. data/gemfiles/sequel-2.11.0.gemfile +8 -0
  74. data/gemfiles/sequel-2.11.0.gemfile.lock +28 -0
  75. data/gemfiles/sequel-2.12.0.gemfile +8 -0
  76. data/gemfiles/sequel-2.12.0.gemfile.lock +28 -0
  77. data/gemfiles/sequel-2.8.0.gemfile +8 -0
  78. data/gemfiles/sequel-2.8.0.gemfile.lock +28 -0
  79. data/gemfiles/sequel-3.0.0.gemfile +8 -0
  80. data/gemfiles/sequel-3.0.0.gemfile.lock +28 -0
  81. data/gemfiles/sequel-3.13.0.gemfile +8 -0
  82. data/gemfiles/sequel-3.13.0.gemfile.lock +28 -0
  83. data/gemfiles/sequel-3.14.0.gemfile +8 -0
  84. data/gemfiles/sequel-3.14.0.gemfile.lock +28 -0
  85. data/gemfiles/sequel-3.23.0.gemfile +8 -0
  86. data/gemfiles/sequel-3.23.0.gemfile.lock +28 -0
  87. data/gemfiles/sequel-3.24.0.gemfile +8 -0
  88. data/gemfiles/sequel-3.24.0.gemfile.lock +28 -0
  89. data/lib/state_machine/event.rb +13 -90
  90. data/lib/state_machine/helper_module.rb +17 -0
  91. data/lib/state_machine/integrations/active_model.rb +35 -0
  92. data/lib/state_machine/integrations/active_record.rb +41 -2
  93. data/lib/state_machine/integrations/data_mapper.rb +17 -2
  94. data/lib/state_machine/integrations/mongo_mapper.rb +34 -7
  95. data/lib/state_machine/integrations/mongoid.rb +34 -26
  96. data/lib/state_machine/integrations/mongoid/versions.rb +29 -3
  97. data/lib/state_machine/integrations/sequel.rb +22 -72
  98. data/lib/state_machine/integrations/sequel/versions.rb +87 -6
  99. data/lib/state_machine/machine.rb +279 -19
  100. data/lib/state_machine/state.rb +2 -2
  101. data/lib/state_machine/state_context.rb +133 -0
  102. data/lib/state_machine/version.rb +3 -0
  103. data/state_machine.gemspec +22 -0
  104. data/test/test_helper.rb +1 -3
  105. data/test/unit/branch_test.rb +1 -3
  106. data/test/unit/event_collection_test.rb +3 -3
  107. data/test/unit/event_test.rb +1 -3
  108. data/test/unit/helper_module_test.rb +17 -0
  109. data/test/unit/integrations/active_model_test.rb +0 -4
  110. data/test/unit/integrations/active_record_test.rb +50 -9
  111. data/test/unit/integrations/data_mapper_test.rb +267 -253
  112. data/test/unit/integrations/mongo_mapper_test.rb +47 -15
  113. data/test/unit/integrations/mongoid_test.rb +50 -8
  114. data/test/unit/integrations/sequel_test.rb +10 -6
  115. data/test/unit/machine_test.rb +206 -25
  116. data/test/unit/state_context_test.rb +421 -0
  117. data/test/unit/state_test.rb +20 -3
  118. metadata +303 -128
  119. data/lib/state_machine/condition_proxy.rb +0 -94
  120. data/test/unit/condition_proxy_test.rb +0 -328
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ .bundle
3
+ coverage
4
+ doc
5
+ pkg
6
+ rdoc
7
+ test/active_record.log
8
+ test/data_mapper.log
9
+ test/mongo_mapper.log
10
+ test/sequel.log
11
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ script: "bundle exec rake appraisal:integration test"
2
+ rvm:
3
+ - 1.8.6
4
+ - 1.8.7
5
+ - 1.9.1
6
+ - 1.9.2
7
+ env:
8
+ - INTEGRATION=default TRAVIS=true
9
+ - INTEGRATION=active_model TRAVIS=true
10
+ - INTEGRATION=active_record TRAVIS=true
11
+ - INTEGRATION=data_mapper TRAVIS=true
12
+ - INTEGRATION=mongoid TRAVIS=true
13
+ - INTEGRATION=mongo_mapper TRAVIS=true
14
+ - INTEGRATION=sequel TRAVIS=true
15
+ notifications:
16
+ disabled: true
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --title "state_machine"
2
+ --readme README.rdoc
3
+ -
4
+ CHANGELOG.rdoc
5
+ LICENSE
data/Appraisals ADDED
@@ -0,0 +1,260 @@
1
+ appraise "default" do
2
+ end
3
+
4
+ # ActiveRecord integrations
5
+ if RUBY_VERSION < "1.9.1"
6
+ appraise "active_record-2.0.0" do
7
+ gem "sqlite3-ruby", "1.3.1"
8
+ gem "activerecord", "2.0.0"
9
+ end
10
+
11
+ appraise "active_record-2.0.5" do
12
+ gem "sqlite3-ruby", "1.3.1"
13
+ gem "activerecord", "2.0.5"
14
+ end
15
+
16
+ appraise "active_record-2.1.0" do
17
+ gem "sqlite3-ruby", "1.3.1"
18
+ gem "activerecord", "2.1.0"
19
+ end
20
+
21
+ appraise "active_record-2.1.2" do
22
+ gem "sqlite3-ruby", "1.3.1"
23
+ gem "activerecord", "2.1.2"
24
+ end
25
+
26
+ appraise "active_record-2.2.3" do
27
+ gem "sqlite3-ruby", "1.3.1"
28
+ gem "activerecord", "2.2.3"
29
+ end
30
+ end
31
+
32
+ appraise "active_record-2.3.12" do
33
+ gem "sqlite3-ruby", "1.3.1"
34
+ gem "activerecord", "2.3.12"
35
+ end
36
+
37
+ if RUBY_VERSION > "1.8.6"
38
+ appraise "active_record-3.0.0" do
39
+ gem "sqlite3-ruby"
40
+ gem "activerecord", "3.0.0"
41
+ end
42
+
43
+ appraise "active_record-3.0.5" do
44
+ gem "sqlite3-ruby"
45
+ gem "activerecord", "3.0.5"
46
+ end
47
+ end
48
+
49
+ # ActiveModel integrations
50
+ if RUBY_VERSION > "1.8.6"
51
+ appraise "active_model-3.0.0" do
52
+ gem "activemodel", "3.0.0"
53
+ end
54
+
55
+ appraise "active_model-3.0.5" do
56
+ gem "activemodel", "3.0.5"
57
+ end
58
+ end
59
+
60
+ # MongoMapper integrations
61
+ if RUBY_VERSION > "1.8.6" && RUBY_VERSION < "1.9.1"
62
+ appraise "mongo_mapper-0.5.5" do
63
+ gem "activesupport", "2.3.11"
64
+ gem "mongo_mapper", "0.5.5"
65
+ end
66
+ end
67
+
68
+ if RUBY_VERSION > "1.8.6"
69
+ appraise "mongo_mapper-0.5.8" do
70
+ gem "activesupport", "2.3.11"
71
+ gem "mongo_mapper", "0.5.8"
72
+ end
73
+
74
+ appraise "mongo_mapper-0.6.0" do
75
+ gem "activesupport", "2.3.11"
76
+ gem "mongo_mapper", "0.6.0"
77
+ end
78
+
79
+ appraise "mongo_mapper-0.6.10" do
80
+ gem "activesupport", "2.3.11"
81
+ gem "mongo_mapper", "0.6.10"
82
+ end
83
+
84
+ appraise "mongo_mapper-0.7.0" do
85
+ gem "activesupport", "2.3.11"
86
+ gem "mongo_mapper", "0.7.0"
87
+ end
88
+
89
+ appraise "mongo_mapper-0.7.5" do
90
+ gem "activesupport", "2.3.11"
91
+ gem "mongo_mapper", "0.7.5"
92
+ end
93
+
94
+ appraise "mongo_mapper-0.8.0" do
95
+ gem "activesupport", "2.3.11"
96
+ gem "mongo", "1.0.1"
97
+ gem "plucky", "0.3.0"
98
+ gem "mongo_mapper", "0.8.0"
99
+ end
100
+
101
+ appraise "mongo_mapper-0.8.3" do
102
+ gem "activesupport", "2.3.11"
103
+ gem "mongo", "1.0.1"
104
+ gem "plucky", "0.3.3"
105
+ gem "mongo_mapper", "0.8.3"
106
+ end
107
+
108
+ appraise "mongo_mapper-0.8.4" do
109
+ gem "activesupport", "2.3.11"
110
+ gem "mongo_mapper", "0.8.4"
111
+ end
112
+
113
+ appraise "mongo_mapper-0.8.6" do
114
+ gem "activesupport", "2.3.11"
115
+ gem "mongo_mapper", "0.8.6"
116
+ end
117
+
118
+ # MongoMapper 0.9.0+ breaks on Ruby 1.9.1
119
+ if RUBY_VERSION != "1.9.1"
120
+ appraise "mongo_mapper-0.9.0" do
121
+ gem "mongo_mapper", "0.9.0"
122
+ end
123
+ end
124
+ end
125
+
126
+ # Mongoid integrations
127
+ if RUBY_VERSION > "1.8.6"
128
+ appraise "mongoid-2.0.0" do
129
+ gem "mongoid", "2.0.0"
130
+ end
131
+
132
+ appraise "mongoid-2.1.4" do
133
+ gem "mongoid", "2.1.4"
134
+ end
135
+ end
136
+
137
+ # Sequel integrations
138
+ appraise "sequel-2.8.0" do
139
+ gem "sqlite3-ruby", "1.3.1"
140
+ gem "sequel", "2.8.0"
141
+ end
142
+
143
+ appraise "sequel-2.11.0" do
144
+ gem "sqlite3-ruby", "1.3.1"
145
+ gem "sequel", "2.11.0"
146
+ end
147
+
148
+ appraise "sequel-2.12.0" do
149
+ gem "sqlite3-ruby", "1.3.1"
150
+ gem "sequel", "2.12.0"
151
+ end
152
+
153
+ appraise "sequel-3.0.0" do
154
+ gem "sqlite3-ruby", "1.3.1"
155
+ gem "sequel", "3.0.0"
156
+ end
157
+
158
+ appraise "sequel-3.13.0" do
159
+ gem "sqlite3-ruby", "1.3.1"
160
+ gem "sequel", "3.13.0"
161
+ end
162
+
163
+ appraise "sequel-3.14.0" do
164
+ gem "sqlite3-ruby", "1.3.1"
165
+ gem "sequel", "3.14.0"
166
+ end
167
+
168
+ appraise "sequel-3.23.0" do
169
+ gem "sqlite3-ruby", "1.3.1"
170
+ gem "sequel", "3.23.0"
171
+ end
172
+
173
+ appraise "sequel-3.24.0" do
174
+ gem "sqlite3-ruby", "1.3.1"
175
+ gem "sequel", "3.24.0"
176
+ end
177
+
178
+ # DataMapper
179
+ if RUBY_VERSION < "1.9.1"
180
+ appraise "data_mapper-0.9.4" do
181
+ gem "dm-core", "0.9.4"
182
+ gem "dm-migrations", "0.9.4"
183
+ gem "dm-validations", "0.9.4"
184
+ gem "dm-observer", "0.9.4"
185
+ gem "data_objects", "0.9.4"
186
+ gem "do_sqlite3", "0.9.4"
187
+ end
188
+
189
+ appraise "data_mapper-0.9.7" do
190
+ gem "dm-core", "0.9.7"
191
+ gem "dm-migrations", "0.9.7"
192
+ gem "dm-validations", "0.9.7"
193
+ gem "dm-observer", "0.9.7"
194
+ gem "data_objects", "0.9.7"
195
+ gem "do_sqlite3", "0.9.7"
196
+ end
197
+
198
+ appraise "data_mapper-0.9.11" do
199
+ gem "dm-core", "0.9.11"
200
+ gem "dm-migrations", "0.9.11"
201
+ gem "dm-validations", "0.9.11"
202
+ gem "dm-observer", "0.9.11"
203
+ gem "data_objects", "0.9.11"
204
+ gem "do_sqlite3", "0.9.11"
205
+ end
206
+
207
+ appraise "data_mapper-0.10.2" do
208
+ gem "dm-core", "0.10.2"
209
+ gem "dm-migrations", "0.10.2"
210
+ gem "dm-validations", "0.10.2"
211
+ gem "dm-observer", "0.10.2"
212
+ gem "data_objects", "0.10.2"
213
+ gem "do_sqlite3", "0.10.2"
214
+ end
215
+
216
+ appraise "data_mapper-0.10.2" do
217
+ gem "dm-core", "0.10.2"
218
+ gem "dm-migrations", "0.10.2"
219
+ gem "dm-validations", "0.10.2"
220
+ gem "dm-observer", "0.10.2"
221
+ gem "data_objects", "0.10.2"
222
+ gem "do_sqlite3", "0.10.2"
223
+ end
224
+ end
225
+
226
+ appraise "data_mapper-1.0.0" do
227
+ gem "dm-core", "1.0.0"
228
+ gem "dm-migrations", "1.0.0"
229
+ gem "dm-validations", "1.0.0"
230
+ gem "dm-observer", "1.0.0"
231
+ gem "dm-transactions", "1.0.0"
232
+ gem "dm-sqlite-adapter", "1.0.0"
233
+ end
234
+
235
+ appraise "data_mapper-1.0.1" do
236
+ gem "dm-core", "1.0.1"
237
+ gem "dm-migrations", "1.0.1"
238
+ gem "dm-validations", "1.0.1"
239
+ gem "dm-observer", "1.0.1"
240
+ gem "dm-transactions", "1.0.1"
241
+ gem "dm-sqlite-adapter", "1.0.1"
242
+ end
243
+
244
+ appraise "data_mapper-1.0.2" do
245
+ gem "dm-core", "1.0.2"
246
+ gem "dm-migrations", "1.0.2"
247
+ gem "dm-validations", "1.0.2"
248
+ gem "dm-observer", "1.0.2"
249
+ gem "dm-transactions", "1.0.2"
250
+ gem "dm-sqlite-adapter", "1.0.2"
251
+ end
252
+
253
+ appraise "data_mapper-1.1.0" do
254
+ gem "dm-core", "1.1.0"
255
+ gem "dm-migrations", "1.1.0"
256
+ gem "dm-validations", "1.1.0"
257
+ gem "dm-observer", "1.1.0"
258
+ gem "dm-transactions", "1.1.0"
259
+ gem "dm-sqlite-adapter", "1.1.0"
260
+ end
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,20 @@
1
1
  == master
2
2
 
3
+ == 1.0.2 / 2011-08-09
4
+
5
+ * Allow transitions to be defined within a state, event, or machine context
6
+ * Use supported framework hooks for integrating Sequel 3.24.0+
7
+ * Use appraisal for testing integrations
8
+ * Improve documentation on the handling of method conflicts
9
+ * Update Mongoid integration for 2.1.0+ support
10
+ * Fix ActiveRecord machine state predicates incorrectly calling superclass implementation when using targeted attributes
11
+ * Fix error when defining states with the same name as the state's machine in ActiveRecord, MongoMapper, and Mongoid integrations
12
+ * Fix machine state predicate not calling superclass implementation if defined after machine definition
13
+ * Generate warnings when defining a helper method more than once
14
+ * Fix multiple machines not being able to target the same attribute if all possible states aren't defined in each
15
+ * Fix ActiveModel / DataMapper integrations not overriding StateMachine::Machine#after_initialize properly
16
+ * Improve documentation for overriding states and integration transactions
17
+
3
18
  == 1.0.1 / 2011-05-30
4
19
 
5
20
  * Add the ability to ignore method conflicts for helpers
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- == state_machine
1
+ == state_machine http://travis-ci.org/pluginaweek/state_machine.png
2
2
 
3
3
  +state_machine+ adds support for creating state machines for attributes on any
4
4
  Ruby class.
@@ -11,16 +11,24 @@ API
11
11
 
12
12
  Bugs
13
13
 
14
- * http://pluginaweek.lighthouseapp.com/projects/13288-state_machine
14
+ * http://github.com/pluginaweek/state_machine/issues
15
15
 
16
16
  Development
17
17
 
18
18
  * http://github.com/pluginaweek/state_machine
19
19
 
20
+ Testing
21
+
22
+ * http://travis-ci.org/pluginaweek/state_machine
23
+
20
24
  Source
21
25
 
22
26
  * git://github.com/pluginaweek/state_machine.git
23
27
 
28
+ Mailing List
29
+
30
+ * http://groups.google.com/group/pluginaweek-talk
31
+
24
32
  == Description
25
33
 
26
34
  State machines make it dead-simple to manage the behavior of a class. Too often,
@@ -49,6 +57,7 @@ Some brief, high-level features include:
49
57
  * Inheritance
50
58
  * Internationalization
51
59
  * GraphViz visualization creator
60
+ * Flexible machine syntax
52
61
 
53
62
  Examples of the usage patterns for some of the above features are shown below.
54
63
  You can find much more detailed documentation in the actual API.
@@ -581,11 +590,21 @@ errors and callbacks. For example,
581
590
  For more information about the various behaviors added for Sequel state
582
591
  machines, see StateMachine::Integrations::Sequel.
583
592
 
584
- == Compatibility
593
+ == Syntax flexibility
585
594
 
586
595
  Although state_machine introduces a simplified syntax, it still remains
587
- backwards compatible with previous versions and other state-related libraries.
588
- For example, transitions and callbacks can continue to be defined like so:
596
+ backwards compatible with previous versions and other state-related libraries by
597
+ providing some flexibility around how transitions are defined. See below for an
598
+ overview of these syntaxes.
599
+
600
+ === Verbose syntax
601
+
602
+ In general, it's recommended that state machines use the implicit syntax for
603
+ transitions. However, you can be a little more explicit and verbose about
604
+ transitions by using the <tt>:from</tt>, <tt>:except_from</tt>, <tt>:to</tt>,
605
+ and <tt>:except_to</tt> options.
606
+
607
+ For example, transitions and callbacks can be defined like so:
589
608
 
590
609
  class Vehicle
591
610
  state_machine :initial => :parked do
@@ -600,9 +619,64 @@ For example, transitions and callbacks can continue to be defined like so:
600
619
  end
601
620
  end
602
621
 
603
- Although this verbose syntax will most likely always be supported, it is
604
- recommended that any state machines eventually migrate to the syntax introduced
605
- in version 0.6.0.
622
+ === Transition context
623
+
624
+ Some flexibility is provided around the context in which transitions can be
625
+ defined. In almost all examples throughout the documentation, transitions are
626
+ defined within the context of an event. If you prefer to have state machines
627
+ defined in the context of a *state* either out of preference or in order to
628
+ easily migrate from a different library, you can do so as shown below:
629
+
630
+ class Vehicle
631
+ state_machine :initial => :parked do
632
+ ...
633
+
634
+ state :parked do
635
+ transition :to => :idling, :on => [:ignite, :shift_up], :if => :seatbelt_on?
636
+
637
+ def speed
638
+ 0
639
+ end
640
+ end
641
+
642
+ state :first_gear do
643
+ transition :to => :second_gear, :on => :shift_up
644
+
645
+ def speed
646
+ 10
647
+ end
648
+ end
649
+
650
+ state :idling, :first_gear do
651
+ transition :to => :parked, :on => :park
652
+ end
653
+ end
654
+ end
655
+
656
+ In the above example, there's no need to specify the +from+ state for each
657
+ transition since it's inferred from the context.
658
+
659
+ You can also define transitions completely outside the context of a particular
660
+ state / event. This may be useful in cases where you're building a state
661
+ machine from a data store instead of part of the class definition. See the
662
+ example below:
663
+
664
+ class Vehicle
665
+ state_machine :initial => :parked do
666
+ ...
667
+
668
+ transition :parked => :idling, :on => [:ignite, :shift_up]
669
+ transition :first_gear => :second_gear, :second_gear => :third_gear, :on => :shift_up
670
+ transition [:idling, :first_gear] => :parked, :on => :park
671
+ transition [:idling, :first_gear] => :parked, :on => :park
672
+ transition all - [:parked, :stalled] => :stalled, :unless => :auto_shop_busy?
673
+ end
674
+ end
675
+
676
+ Notice that in these alternative syntaxes:
677
+ * You can continue to configure <tt>:if</tt> and <tt>:unless</tt> conditions
678
+ * You can continue to define +from+ states (when in the machine context) using
679
+ the +all+, +any+, and +same+ helper methods
606
680
 
607
681
  == Tools
608
682
 
@@ -638,7 +712,63 @@ in the class. The generated files will use an output filename of the format
638
712
  For examples of actual images generated using this task, see those under the
639
713
  examples folder.
640
714
 
641
- ==== Ruby on Rails Integration
715
+ === Interactive graphs
716
+
717
+ Jean Bovet's {Visual Automata Simulator}[http://www.cs.usfca.edu/~jbovet/vas.html]
718
+ is a great tool for "simulating, visualizing and transforming finite state
719
+ automata and Turing Machines". It can help in the creation of states and events
720
+ for your models. It is cross-platform, written in Java.
721
+
722
+ == Web Frameworks
723
+
724
+ === Ruby on Rails
725
+
726
+ Integrating state_machine into your Ruby on Rails application is straightforward
727
+ and provides a few additional features specific to the framework. To get
728
+ started, following the steps below.
729
+
730
+ ==== 1. Install the gem
731
+
732
+ If using Rails 2.x:
733
+
734
+ # In config/environment.rb
735
+ ...
736
+ Rails::Initializer.run do |config|
737
+ ...
738
+ config.gem 'state_machine', :version => '~> 1.0'
739
+ ...
740
+ end
741
+
742
+ If using Rails 3.x or up:
743
+
744
+ # In Gemfile
745
+ ...
746
+ gem 'state_machine'
747
+ gem 'ruby-graphviz', :require => 'graphviz' # Optional: only required for graphing
748
+
749
+ As usual, run <tt>bundle install</tt> to load the gems.
750
+
751
+ ==== 2. Create a model
752
+
753
+ Create a model with a field to store the state, along with other any other
754
+ fields your application requires:
755
+
756
+ $ rails generate model Vehicle state:string
757
+ $ rake db:migrate
758
+
759
+ ==== 3. Configure the state machine
760
+
761
+ Add the state machine to your model. Following the examples above,
762
+ +app/models/vehicle.rb+ might become:
763
+
764
+ class Vehicle < ActiveRecord::Base
765
+ state_machine :initial => :parked do
766
+ before_transition :parked => any - :parked, :do => :put_on_seatbelt
767
+ ...
768
+ end
769
+ end
770
+
771
+ ==== Rake tasks
642
772
 
643
773
  There is a special integration Rake task for generating state machines for
644
774
  classes used in a Ruby on Rails application. This task will load the application
@@ -653,12 +783,9 @@ to the end of your application's Rakefile in order for the above task to work:
653
783
 
654
784
  require 'tasks/state_machine'
655
785
 
656
- If you are using Rails 3.0+, you must also add the following to your
657
- application's Gemfile:
658
-
659
- gem 'ruby-graphviz', :require => 'graphviz'
786
+ === Merb
660
787
 
661
- ==== Merb Integration
788
+ ==== Rake tasks
662
789
 
663
790
  Like Ruby on Rails, there is a special integration Rake task for generating
664
791
  state machines for classes used in a Merb application. This task will load the
@@ -669,27 +796,27 @@ For example,
669
796
 
670
797
  rake state_machine:draw CLASS=Vehicle
671
798
 
672
- === Interactive graphs
673
-
674
- Jean Bovet's {Visual Automata Simulator}[http://www.cs.usfca.edu/~jbovet/vas.html]
675
- is a great tool for "simulating, visualizing and transforming finite state
676
- automata and Turing Machines". It can help in the creation of states and events
677
- for your models. It is cross-platform, written in Java.
678
-
679
799
  == Testing
680
800
 
681
801
  To run the core test suite (does *not* test any of the integrations):
682
802
 
683
- rake test
803
+ bundle install
804
+ bundle exec rake test
805
+
806
+ To run integration tests:
807
+
808
+ bundle install
809
+ rake appraisal:install
810
+ rake appraisal:test
684
811
 
685
- Test specific versions of integrations like so:
812
+ You can also test a specific version:
686
813
 
687
- rake test INTEGRATION=active_model VERSION=3.0.0
688
- rake test INTEGRATION=active_record VERSION=2.0.0
689
- rake test INTEGRATION=data_mapper VERSION=0.9.4
690
- rake test INTEGRATION=mongoid VERSION=2.0.0
691
- rake test INTEGRATION=mongo_mapper VERSION=0.5.5
692
- rake test INTEGRATION=sequel VERSION=2.8.0
814
+ rake appraisal:active_model-3.0.0 test
815
+ rake appraisal:active_record-2.0.0 test
816
+ rake appraisal:data_mapper-0.9.4 test
817
+ rake appraisal:mongoid-2.0.0 test
818
+ rake appraisal:mongo_mapper-0.5.5 test
819
+ rake appraisal:sequel-2.8.0 test
693
820
 
694
821
  == Caveats
695
822