aasm 4.12.2 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +393 -116
  4. data/lib/aasm/aasm.rb +30 -27
  5. data/lib/aasm/base.rb +64 -11
  6. data/lib/aasm/configuration.rb +6 -0
  7. data/lib/aasm/core/event.rb +26 -30
  8. data/lib/aasm/core/invoker.rb +129 -0
  9. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  10. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  11. data/lib/aasm/core/invokers/literal_invoker.rb +49 -0
  12. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  13. data/lib/aasm/core/state.rb +16 -14
  14. data/lib/aasm/core/transition.rb +8 -69
  15. data/lib/aasm/dsl_helper.rb +24 -22
  16. data/lib/aasm/errors.rb +5 -3
  17. data/lib/aasm/instance_base.rb +34 -3
  18. data/lib/aasm/localizer.rb +13 -3
  19. data/lib/aasm/persistence/active_record_persistence.rb +25 -5
  20. data/lib/aasm/persistence/base.rb +14 -3
  21. data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
  22. data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
  23. data/lib/aasm/persistence/mongoid_persistence.rb +1 -1
  24. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  25. data/lib/aasm/persistence/orm.rb +26 -14
  26. data/lib/aasm/persistence/plain_persistence.rb +2 -1
  27. data/lib/aasm/persistence/redis_persistence.rb +1 -1
  28. data/lib/aasm/persistence/sequel_persistence.rb +0 -1
  29. data/lib/aasm/persistence.rb +3 -0
  30. data/lib/aasm/rspec/allow_event.rb +5 -1
  31. data/lib/aasm/rspec/allow_transition_to.rb +5 -1
  32. data/lib/aasm/rspec/transition_from.rb +5 -1
  33. data/lib/aasm/version.rb +1 -1
  34. data/lib/aasm.rb +5 -2
  35. data/lib/generators/aasm/orm_helpers.rb +7 -1
  36. data/lib/generators/active_record/aasm_generator.rb +3 -1
  37. data/lib/generators/active_record/templates/migration.rb +1 -1
  38. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  39. data/lib/motion-aasm.rb +1 -0
  40. metadata +42 -343
  41. data/.document +0 -6
  42. data/.gitignore +0 -20
  43. data/.travis.yml +0 -52
  44. data/API +0 -34
  45. data/Appraisals +0 -43
  46. data/CHANGELOG.md +0 -365
  47. data/CODE_OF_CONDUCT.md +0 -13
  48. data/CONTRIBUTING.md +0 -24
  49. data/Gemfile +0 -7
  50. data/HOWTO +0 -12
  51. data/PLANNED_CHANGES.md +0 -11
  52. data/README_FROM_VERSION_3_TO_4.md +0 -240
  53. data/Rakefile +0 -31
  54. data/TESTING.md +0 -25
  55. data/aasm.gemspec +0 -35
  56. data/callbacks.txt +0 -51
  57. data/gemfiles/rails_3.2.gemfile +0 -13
  58. data/gemfiles/rails_4.0.gemfile +0 -15
  59. data/gemfiles/rails_4.2.gemfile +0 -16
  60. data/gemfiles/rails_4.2_mongoid_5.gemfile +0 -11
  61. data/gemfiles/rails_5.0.gemfile +0 -14
  62. data/spec/database.rb +0 -44
  63. data/spec/database.yml +0 -3
  64. data/spec/en.yml +0 -12
  65. data/spec/en_deprecated_style.yml +0 -10
  66. data/spec/generators/active_record_generator_spec.rb +0 -47
  67. data/spec/generators/mongoid_generator_spec.rb +0 -31
  68. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +0 -25
  69. data/spec/models/active_record/complex_active_record_example.rb +0 -37
  70. data/spec/models/active_record/derivate_new_dsl.rb +0 -7
  71. data/spec/models/active_record/false_state.rb +0 -35
  72. data/spec/models/active_record/gate.rb +0 -39
  73. data/spec/models/active_record/invalid_persistor.rb +0 -29
  74. data/spec/models/active_record/localizer_test_model.rb +0 -34
  75. data/spec/models/active_record/no_direct_assignment.rb +0 -21
  76. data/spec/models/active_record/no_scope.rb +0 -21
  77. data/spec/models/active_record/persisted_state.rb +0 -12
  78. data/spec/models/active_record/provided_and_persisted_state.rb +0 -24
  79. data/spec/models/active_record/reader.rb +0 -7
  80. data/spec/models/active_record/readme_job.rb +0 -21
  81. data/spec/models/active_record/silent_persistor.rb +0 -29
  82. data/spec/models/active_record/simple_new_dsl.rb +0 -17
  83. data/spec/models/active_record/thief.rb +0 -29
  84. data/spec/models/active_record/transactor.rb +0 -99
  85. data/spec/models/active_record/transient.rb +0 -6
  86. data/spec/models/active_record/validator.rb +0 -118
  87. data/spec/models/active_record/with_enum.rb +0 -39
  88. data/spec/models/active_record/with_enum_without_column.rb +0 -38
  89. data/spec/models/active_record/with_false_enum.rb +0 -31
  90. data/spec/models/active_record/with_true_enum.rb +0 -39
  91. data/spec/models/active_record/worker.rb +0 -2
  92. data/spec/models/active_record/writer.rb +0 -6
  93. data/spec/models/basic_two_state_machines_example.rb +0 -25
  94. data/spec/models/callbacks/basic.rb +0 -98
  95. data/spec/models/callbacks/basic_multiple.rb +0 -75
  96. data/spec/models/callbacks/guard_within_block.rb +0 -67
  97. data/spec/models/callbacks/guard_within_block_multiple.rb +0 -66
  98. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +0 -66
  99. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +0 -65
  100. data/spec/models/callbacks/private_method.rb +0 -44
  101. data/spec/models/callbacks/private_method_multiple.rb +0 -44
  102. data/spec/models/callbacks/with_args.rb +0 -62
  103. data/spec/models/callbacks/with_args_multiple.rb +0 -61
  104. data/spec/models/callbacks/with_state_arg.rb +0 -30
  105. data/spec/models/callbacks/with_state_arg_multiple.rb +0 -26
  106. data/spec/models/complex_example.rb +0 -222
  107. data/spec/models/conversation.rb +0 -93
  108. data/spec/models/default_state.rb +0 -12
  109. data/spec/models/double_definer.rb +0 -21
  110. data/spec/models/dynamoid/complex_dynamoid_example.rb +0 -37
  111. data/spec/models/dynamoid/dynamoid_multiple.rb +0 -18
  112. data/spec/models/dynamoid/dynamoid_simple.rb +0 -18
  113. data/spec/models/foo.rb +0 -106
  114. data/spec/models/foo_callback_multiple.rb +0 -45
  115. data/spec/models/guard_arguments_check.rb +0 -17
  116. data/spec/models/guard_with_params.rb +0 -24
  117. data/spec/models/guard_with_params_multiple.rb +0 -18
  118. data/spec/models/guardian.rb +0 -58
  119. data/spec/models/guardian_multiple.rb +0 -48
  120. data/spec/models/guardian_without_from_specified.rb +0 -18
  121. data/spec/models/initial_state_proc.rb +0 -31
  122. data/spec/models/mongoid/complex_mongoid_example.rb +0 -37
  123. data/spec/models/mongoid/invalid_persistor_mongoid.rb +0 -39
  124. data/spec/models/mongoid/mongoid_relationships.rb +0 -26
  125. data/spec/models/mongoid/no_scope_mongoid.rb +0 -21
  126. data/spec/models/mongoid/silent_persistor_mongoid.rb +0 -39
  127. data/spec/models/mongoid/simple_mongoid.rb +0 -23
  128. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +0 -25
  129. data/spec/models/mongoid/validator_mongoid.rb +0 -100
  130. data/spec/models/multi_transitioner.rb +0 -34
  131. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +0 -31
  132. data/spec/models/namespaced_multiple_example.rb +0 -42
  133. data/spec/models/no_initial_state.rb +0 -25
  134. data/spec/models/not_auto_loaded/process.rb +0 -21
  135. data/spec/models/parametrised_event.rb +0 -42
  136. data/spec/models/parametrised_event_multiple.rb +0 -29
  137. data/spec/models/process_with_new_dsl.rb +0 -31
  138. data/spec/models/provided_state.rb +0 -24
  139. data/spec/models/redis/complex_redis_example.rb +0 -40
  140. data/spec/models/redis/redis_multiple.rb +0 -20
  141. data/spec/models/redis/redis_simple.rb +0 -20
  142. data/spec/models/sequel/complex_sequel_example.rb +0 -46
  143. data/spec/models/sequel/invalid_persistor.rb +0 -52
  144. data/spec/models/sequel/sequel_multiple.rb +0 -25
  145. data/spec/models/sequel/sequel_simple.rb +0 -26
  146. data/spec/models/sequel/silent_persistor.rb +0 -50
  147. data/spec/models/sequel/transactor.rb +0 -112
  148. data/spec/models/sequel/validator.rb +0 -93
  149. data/spec/models/sequel/worker.rb +0 -12
  150. data/spec/models/silencer.rb +0 -27
  151. data/spec/models/simple_custom_example.rb +0 -53
  152. data/spec/models/simple_example.rb +0 -15
  153. data/spec/models/simple_multiple_example.rb +0 -42
  154. data/spec/models/state_machine_with_failed_event.rb +0 -20
  155. data/spec/models/states_on_one_line_example.rb +0 -8
  156. data/spec/models/sub_class.rb +0 -41
  157. data/spec/models/sub_class_with_more_states.rb +0 -18
  158. data/spec/models/sub_classing.rb +0 -3
  159. data/spec/models/super_class.rb +0 -46
  160. data/spec/models/this_name_better_not_be_in_use.rb +0 -11
  161. data/spec/models/valid_state_name.rb +0 -23
  162. data/spec/spec_helper.rb +0 -26
  163. data/spec/spec_helpers/active_record.rb +0 -7
  164. data/spec/spec_helpers/dynamoid.rb +0 -33
  165. data/spec/spec_helpers/mongoid.rb +0 -7
  166. data/spec/spec_helpers/redis.rb +0 -15
  167. data/spec/spec_helpers/remove_warnings.rb +0 -1
  168. data/spec/spec_helpers/sequel.rb +0 -7
  169. data/spec/unit/api_spec.rb +0 -100
  170. data/spec/unit/basic_two_state_machines_example_spec.rb +0 -10
  171. data/spec/unit/callback_multiple_spec.rb +0 -300
  172. data/spec/unit/callbacks_spec.rb +0 -491
  173. data/spec/unit/complex_example_spec.rb +0 -84
  174. data/spec/unit/complex_multiple_example_spec.rb +0 -99
  175. data/spec/unit/edge_cases_spec.rb +0 -16
  176. data/spec/unit/event_multiple_spec.rb +0 -73
  177. data/spec/unit/event_naming_spec.rb +0 -16
  178. data/spec/unit/event_spec.rb +0 -381
  179. data/spec/unit/exception_spec.rb +0 -11
  180. data/spec/unit/guard_arguments_check_spec.rb +0 -9
  181. data/spec/unit/guard_multiple_spec.rb +0 -60
  182. data/spec/unit/guard_spec.rb +0 -89
  183. data/spec/unit/guard_with_params_multiple_spec.rb +0 -10
  184. data/spec/unit/guard_with_params_spec.rb +0 -14
  185. data/spec/unit/guard_without_from_specified_spec.rb +0 -10
  186. data/spec/unit/initial_state_multiple_spec.rb +0 -15
  187. data/spec/unit/initial_state_spec.rb +0 -12
  188. data/spec/unit/inspection_multiple_spec.rb +0 -201
  189. data/spec/unit/inspection_spec.rb +0 -149
  190. data/spec/unit/localizer_spec.rb +0 -78
  191. data/spec/unit/memory_leak_spec.rb +0 -38
  192. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +0 -14
  193. data/spec/unit/namespaced_multiple_example_spec.rb +0 -75
  194. data/spec/unit/new_dsl_spec.rb +0 -12
  195. data/spec/unit/override_warning_spec.rb +0 -94
  196. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +0 -618
  197. data/spec/unit/persistence/active_record_persistence_spec.rb +0 -721
  198. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +0 -135
  199. data/spec/unit/persistence/dynamoid_persistence_spec.rb +0 -84
  200. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +0 -204
  201. data/spec/unit/persistence/mongoid_persistence_spec.rb +0 -169
  202. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +0 -88
  203. data/spec/unit/persistence/redis_persistence_spec.rb +0 -53
  204. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +0 -148
  205. data/spec/unit/persistence/sequel_persistence_spec.rb +0 -368
  206. data/spec/unit/readme_spec.rb +0 -41
  207. data/spec/unit/reloading_spec.rb +0 -15
  208. data/spec/unit/rspec_matcher_spec.rb +0 -79
  209. data/spec/unit/simple_custom_example_spec.rb +0 -39
  210. data/spec/unit/simple_example_spec.rb +0 -42
  211. data/spec/unit/simple_multiple_example_spec.rb +0 -91
  212. data/spec/unit/state_spec.rb +0 -89
  213. data/spec/unit/states_on_one_line_example_spec.rb +0 -16
  214. data/spec/unit/subclassing_multiple_spec.rb +0 -74
  215. data/spec/unit/subclassing_spec.rb +0 -46
  216. data/spec/unit/transition_spec.rb +0 -436
  217. data/test/minitest_helper.rb +0 -57
  218. data/test/unit/minitest_matcher_test.rb +0 -80
data/README.md CHANGED
@@ -2,16 +2,62 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/aasm.svg)](http://badge.fury.io/rb/aasm)
4
4
  [![Build Status](https://travis-ci.org/aasm/aasm.svg?branch=master)](https://travis-ci.org/aasm/aasm)
5
- [![Dependency Status](https://gemnasium.com/aasm/aasm.svg)](https://gemnasium.com/aasm/aasm)
6
5
  [![Code Climate](https://codeclimate.com/github/aasm/aasm/badges/gpa.svg)](https://codeclimate.com/github/aasm/aasm)
6
+ [![codecov](https://codecov.io/gh/aasm/aasm/branch/master/graph/badge.svg)](https://codecov.io/gh/aasm/aasm)
7
+
8
+ ## Index
9
+ - [Upgrade from version 3 to 4](#upgrade-from-version-3-to-4)
10
+ - [Usage](#usage)
11
+ - [Callbacks](#callbacks)
12
+ - [Lifecycle](#lifecycle)
13
+ - [The current event triggered](#the-current-event-triggered)
14
+ - [Guards](#guards)
15
+ - [Transitions](#transitions)
16
+ - [Multiple state machines per class](#multiple-state-machines-per-class)
17
+ - [Handling naming conflicts between multiple state machines](#handling-naming-conflicts-between-multiple-state-machines)
18
+ - [Binding event](#binding-event)
19
+ - [Auto-generated Status Constants](#auto-generated-status-constants)
20
+ - [Extending AASM](#extending-aasm)
21
+ - [ActiveRecord](#activerecord)
22
+ - [Bang events](#bang-events)
23
+ - [Timestamps](#timestamps)
24
+ - [ActiveRecord enums](#activerecord-enums)
25
+ - [Sequel](#sequel)
26
+ - [Dynamoid](#dynamoid)
27
+ - [Mongoid](#mongoid)
28
+ - [Nobrainer](#nobrainer)
29
+ - [Redis](#redis)
30
+ - [Automatic Scopes](#automatic-scopes)
31
+ - [Transaction support](#transaction-support)
32
+ - [Pessimistic Locking](#pessimistic-locking)
33
+ - [Column name & migration](#column-name--migration)
34
+ - [Log State Changes](#log-state-changes)
35
+ - [Inspection](#inspection)
36
+ - [Warning output](#warning-output)
37
+ - [RubyMotion support](#rubymotion-support)
38
+ - [Testing](#testing)
39
+ - [RSpec](#rspec)
40
+ - [Minitest](#minitest)
41
+ - [Assertions](#assertions)
42
+ - [Expectations](#expectations)
43
+ - [Installation](#installation)
44
+ - [Manually from RubyGems.org](#manually-from-rubygemsorg)
45
+ - [Bundler](#or-if-you-are-using-bundler)
46
+ - [Building your own gems](#building-your-own-gems)
47
+ - [Generators](#generators)
48
+ - [Test suite with Docker](#docker)
49
+ - [Latest changes](#latest-changes)
50
+ - [Questions?](#questions)
51
+ - [Maintainers](#maintainers)
52
+ - [Contributing](CONTRIBUTING.md)
53
+ - [Warranty](#warranty)
54
+ - [License](#license)
7
55
 
8
56
  This package contains AASM, a library for adding finite state machines to Ruby classes.
9
57
 
10
58
  AASM started as the *acts_as_state_machine* plugin but has evolved into a more generic library
11
- that no longer targets only ActiveRecord models. It currently provides adapters for
12
- [ActiveRecord](http://api.rubyonrails.org/classes/ActiveRecord/Base.html),
13
- and [Mongoid](http://mongoid.org/) but it can be used for any Ruby class, no matter what
14
- parent class it has (if any).
59
+ that no longer targets only ActiveRecord models. It currently provides adapters for many
60
+ ORMs but it can be used for any Ruby class, no matter what parent class it has (if any).
15
61
 
16
62
  ## Upgrade from version 3 to 4
17
63
 
@@ -27,19 +73,19 @@ class Job
27
73
  include AASM
28
74
 
29
75
  aasm do
30
- state :sleeping, :initial => true
76
+ state :sleeping, initial: true
31
77
  state :running, :cleaning
32
78
 
33
79
  event :run do
34
- transitions :from => :sleeping, :to => :running
80
+ transitions from: :sleeping, to: :running
35
81
  end
36
82
 
37
83
  event :clean do
38
- transitions :from => :running, :to => :cleaning
84
+ transitions from: :running, to: :cleaning
39
85
  end
40
86
 
41
87
  event :sleep do
42
- transitions :from => [:running, :cleaning], :to => :sleeping
88
+ transitions from: [:running, :cleaning], to: :sleeping
43
89
  end
44
90
  end
45
91
 
@@ -65,7 +111,7 @@ AASM not to be *whiny*:
65
111
  ```ruby
66
112
  class Job
67
113
  ...
68
- aasm :whiny_transitions => false do
114
+ aasm whiny_transitions: false do
69
115
  ...
70
116
  end
71
117
  end
@@ -86,27 +132,27 @@ the transition succeeds :
86
132
 
87
133
  ### Callbacks
88
134
 
89
- You can define a number of callbacks for your transitions. These methods will be
90
- called, when certain criteria are met, like entering a particular state:
135
+ You can define a number of callbacks for your events, transitions and states. These methods, Procs or classes will be
136
+ called when certain criteria are met, like entering a particular state:
91
137
 
92
138
  ```ruby
93
139
  class Job
94
140
  include AASM
95
141
 
96
142
  aasm do
97
- state :sleeping, :initial => true, :before_enter => :do_something
98
- state :running
143
+ state :sleeping, initial: true, before_enter: :do_something
144
+ state :running, before_enter: Proc.new { do_something && notify_somebody }
99
145
  state :finished
100
146
 
101
147
  after_all_transitions :log_status_change
102
148
 
103
- event :run, :after => :notify_somebody do
149
+ event :run, after: :notify_somebody do
104
150
  before do
105
151
  log('Preparing to run')
106
152
  end
107
153
 
108
- transitions :from => :sleeping, :to => :running, :after => Proc.new {|*args| set_process(*args) }
109
- transitions :from => :running, :to => :finished, :after => LogRunTime
154
+ transitions from: :sleeping, to: :running, after: Proc.new {|*args| set_process(*args) }
155
+ transitions from: :running, to: :finished, after: LogRunTime
110
156
  end
111
157
 
112
158
  event :sleep do
@@ -116,7 +162,7 @@ class Job
116
162
  error do |e|
117
163
  ...
118
164
  end
119
- transitions :from => :running, :to => :sleeping
165
+ transitions from: :running, to: :sleeping
120
166
  end
121
167
  end
122
168
 
@@ -151,6 +197,8 @@ is finished.
151
197
 
152
198
  AASM will also initialize `LogRunTime` and run the `call` method for you after the transition from `running` to `finished` in the example above. You can pass arguments to the class by defining an initialize method on it, like this:
153
199
 
200
+ Note that Procs are executed in the context of a record, it means that you don't need to expect the record as an argument, just call the methods you need.
201
+
154
202
  ```ruby
155
203
  class LogRunTime
156
204
  # optional args parameter can be omitted, but if you define initialize
@@ -165,23 +213,34 @@ class LogRunTime
165
213
  end
166
214
  ```
167
215
 
168
- Also, you can pass parameters to events:
216
+ #### Parameters
217
+ You can pass parameters to events:
169
218
 
170
219
  ```ruby
171
220
  job = Job.new
172
- job.run(:running, :defragmentation)
221
+ job.run(:defragmentation)
173
222
  ```
174
223
 
175
- In this case the `set_process` would be called with `:defragmentation` argument.
224
+ All guards and after callbacks will receive these parameters. In this case `set_process` would be called with
225
+ `:defragmentation` argument.
176
226
 
177
- Note that when passing arguments to a state transition, the first argument must be the desired end state. In the above example, we wish to transition to `:running` state and run the callback with `:defragmentation` argument. You can also pass in `nil` as the desired end state, and AASM will try to transition to the first end state defined for that event.
227
+ If the first argument to the event is a state (e.g. `:running` or `:finished`), the first argument is consumed and
228
+ the state machine will attempt to transition to that state. Add comma separated parameter for guards and callbacks
178
229
 
230
+ ```ruby
231
+ job = Job.new
232
+ job.run(:running, :defragmentation)
233
+ ```
234
+ In this case `set_process` won't be called, job will transition to running state and callback will receive
235
+ `:defragmentation` as parameter
236
+
237
+ #### Error Handling
179
238
  In case of an error during the event processing the error is rescued and passed to `:error`
180
239
  callback, which can handle it or re-raise it for further propagation.
181
240
 
182
241
  Also, you can define a method that will be called if any event fails:
183
242
 
184
- ```
243
+ ```ruby
185
244
  def aasm_event_failed(event_name, old_state_name)
186
245
  # use custom exception/messages, report metrics, etc
187
246
  end
@@ -215,8 +274,8 @@ begin
215
274
  new_state enter
216
275
  ...update state...
217
276
  event before_success # if persist successful
218
- transition success # if persist successful
219
- event success # if persist successful
277
+ transition success # if persist successful, database update not guaranteed
278
+ event success # if persist successful, database update not guaranteed
220
279
  old_state after_exit
221
280
  new_state after_enter
222
281
  event after
@@ -230,6 +289,8 @@ ensure
230
289
  end
231
290
  ```
232
291
 
292
+ Use event's `after_commit` callback if it should be fired after database update.
293
+
233
294
  #### The current event triggered
234
295
 
235
296
  While running the callbacks you can easily retrieve the name of the event triggered
@@ -260,38 +321,38 @@ and then
260
321
  Let's assume you want to allow particular transitions only if a defined condition is
261
322
  given. For this you can set up a guard per transition, which will run before actually
262
323
  running the transition. If the guard returns `false` the transition will be
263
- denied (raising `AASM::InvalidTransition` or returning `false` itself):
324
+ denied (raising `AASM::InvalidTransition`):
264
325
 
265
326
  ```ruby
266
327
  class Cleaner
267
328
  include AASM
268
329
 
269
330
  aasm do
270
- state :idle, :initial => true
331
+ state :idle, initial: true
271
332
  state :cleaning
272
333
 
273
334
  event :clean do
274
- transitions :from => :idle, :to => :cleaning, :guard => :cleaning_needed?
335
+ transitions from: :idle, to: :cleaning, guard: :cleaning_needed?
275
336
  end
276
337
 
277
338
  event :clean_if_needed do
278
- transitions :from => :idle, :to => :cleaning do
339
+ transitions from: :idle, to: :cleaning do
279
340
  guard do
280
341
  cleaning_needed?
281
342
  end
282
343
  end
283
- transitions :from => :idle, :to => :idle
344
+ transitions from: :idle, to: :idle
284
345
  end
285
-
346
+
286
347
  event :clean_if_dirty do
287
- transitions :from => :idle, :to => :cleaning, :guard => :if_dirty?
348
+ transitions from: :idle, to: :cleaning, guard: :if_dirty?
288
349
  end
289
350
  end
290
351
 
291
352
  def cleaning_needed?
292
353
  false
293
354
  end
294
-
355
+
295
356
  def if_dirty?(status)
296
357
  status == :dirty
297
358
  end
@@ -303,7 +364,7 @@ job.clean # => raises AASM::InvalidTransition
303
364
  job.may_clean_if_needed? # => true
304
365
  job.clean_if_needed! # idle
305
366
 
306
- job.clean_if_dirty(:clean) # => false
367
+ job.clean_if_dirty(:clean) # => raises AASM::InvalidTransition
307
368
  job.clean_if_dirty(:dirty) # => true
308
369
  ```
309
370
 
@@ -313,16 +374,16 @@ You can even provide a number of guards, which all have to succeed to proceed
313
374
  def walked_the_dog?; ...; end
314
375
 
315
376
  event :sleep do
316
- transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?, :walked_the_dog?]
377
+ transitions from: :running, to: :sleeping, guards: [:cleaning_needed?, :walked_the_dog?]
317
378
  end
318
379
  ```
319
380
 
320
381
  If you want to provide guards for all transitions within an event, you can use event guards
321
382
 
322
383
  ```ruby
323
- event :sleep, :guards => [:walked_the_dog?] do
324
- transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?]
325
- transitions :from => :cleaning, :to => :sleeping
384
+ event :sleep, guards: [:walked_the_dog?] do
385
+ transitions from: :running, to: :sleeping, guards: [:cleaning_needed?]
386
+ transitions from: :cleaning, to: :sleeping
326
387
  end
327
388
  ```
328
389
 
@@ -330,15 +391,30 @@ If you prefer a more Ruby-like guard syntax, you can use `if` and `unless` as we
330
391
 
331
392
  ```ruby
332
393
  event :clean do
333
- transitions :from => :running, :to => :cleaning, :if => :cleaning_needed?
394
+ transitions from: :running, to: :cleaning, if: :cleaning_needed?
334
395
  end
335
396
 
336
397
  event :sleep do
337
- transitions :from => :running, :to => :sleeping, :unless => :cleaning_needed?
398
+ transitions from: :running, to: :sleeping, unless: :cleaning_needed?
338
399
  end
339
400
  end
340
401
  ```
341
402
 
403
+ You can invoke a Class instead of a method if the Class responds to `call`
404
+
405
+ ```ruby
406
+ event :sleep do
407
+ transitions from: :running, to: :sleeping, guards: Dog
408
+ end
409
+ ```
410
+ ```ruby
411
+ class Dog
412
+ def call
413
+ cleaning_needed? && walked?
414
+ end
415
+ ...
416
+ end
417
+ ```
342
418
 
343
419
  ### Transitions
344
420
 
@@ -351,7 +427,7 @@ class Job
351
427
  include AASM
352
428
 
353
429
  aasm do
354
- state :stage1, :initial => true
430
+ state :stage1, initial: true
355
431
  state :stage2
356
432
  state :stage3
357
433
  state :completed
@@ -372,40 +448,67 @@ job.stage1_completed
372
448
  job.aasm.current_state # stage3
373
449
  ```
374
450
 
451
+ You can define transition from any defined state by omitting `from`:
452
+
453
+ ```ruby
454
+ event :abort do
455
+ transitions to: :aborted
456
+ end
457
+ ```
458
+
459
+ ### Display name for state
460
+
461
+ You can define display name for state using :display option
462
+
463
+ ```ruby
464
+ class Job
465
+ include AASM
466
+
467
+ aasm do
468
+ state :stage1, initial: true, display: 'First Stage'
469
+ state :stage2
470
+ state :stage3
471
+ end
472
+ end
473
+
474
+ job = Job.new
475
+ job.aasm.human_state
476
+
477
+ ```
375
478
 
376
479
  ### Multiple state machines per class
377
480
 
378
481
  Multiple state machines per class are supported. Be aware though that _AASM_ has been
379
- built with one state machine per class in mind. Nonetheless, here's how to do it:
482
+ built with one state machine per class in mind. Nonetheless, here's how to do it (see below). Please note that you will need to specify database columns for where your pertinent states will be stored - we have specified two columns `move_state` and `work_state` in the example below. See the [Column name & migration](https://github.com/aasm/aasm#column-name--migration) section for further info.
380
483
 
381
484
  ```ruby
382
485
  class SimpleMultipleExample
383
486
  include AASM
384
- aasm(:move) do
385
- state :standing, :initial => true
487
+ aasm(:move, column: 'move_state') do
488
+ state :standing, initial: true
386
489
  state :walking
387
490
  state :running
388
491
 
389
492
  event :walk do
390
- transitions :from => :standing, :to => :walking
493
+ transitions from: :standing, to: :walking
391
494
  end
392
495
  event :run do
393
- transitions :from => [:standing, :walking], :to => :running
496
+ transitions from: [:standing, :walking], to: :running
394
497
  end
395
498
  event :hold do
396
- transitions :from => [:walking, :running], :to => :standing
499
+ transitions from: [:walking, :running], to: :standing
397
500
  end
398
501
  end
399
502
 
400
- aasm(:work) do
401
- state :sleeping, :initial => true
503
+ aasm(:work, column: 'work_state') do
504
+ state :sleeping, initial: true
402
505
  state :processing
403
506
 
404
507
  event :start do
405
- transitions :from => :sleeping, :to => :processing
508
+ transitions from: :sleeping, to: :processing
406
509
  end
407
510
  event :stop do
408
- transitions :from => :processing, :to => :sleeping
511
+ transitions from: :processing, to: :sleeping
409
512
  end
410
513
  end
411
514
  end
@@ -414,26 +517,72 @@ simple = SimpleMultipleExample.new
414
517
 
415
518
  simple.aasm(:move).current_state
416
519
  # => :standing
417
- simple.aasm(:work).current
520
+ simple.aasm(:work).current_state
418
521
  # => :sleeping
419
522
 
420
523
  simple.start
421
524
  simple.aasm(:move).current_state
422
525
  # => :standing
423
- simple.aasm(:work).current
526
+ simple.aasm(:work).current_state
424
527
  # => :processing
425
528
 
426
529
  ```
427
530
 
428
- _AASM_ doesn't prohibit to define the same event in more than one state machine. The
429
- latest definition "wins" and overrides previous definitions. Nonetheless, a warning is issued:
531
+ #### Handling naming conflicts between multiple state machines
532
+
533
+ _AASM_ doesn't prohibit to define the same event in more than one state
534
+ machine. If no namespace is provided, the latest definition "wins" and
535
+ overrides previous definitions. Nonetheless, a warning is issued:
430
536
  `SimpleMultipleExample: overriding method 'run'!`.
431
537
 
538
+ Alternatively, you can provide a namespace for each state machine:
539
+
540
+ ```ruby
541
+ class NamespacedMultipleExample
542
+ include AASM
543
+ aasm(:status) do
544
+ state :unapproved, initial: true
545
+ state :approved
546
+
547
+ event :approve do
548
+ transitions from: :unapproved, to: :approved
549
+ end
550
+
551
+ event :unapprove do
552
+ transitions from: :approved, to: :unapproved
553
+ end
554
+ end
555
+
556
+ aasm(:review_status, namespace: :review) do
557
+ state :unapproved, initial: true
558
+ state :approved
559
+
560
+ event :approve do
561
+ transitions from: :unapproved, to: :approved
562
+ end
563
+
564
+ event :unapprove do
565
+ transitions from: :approved, to: :unapproved
566
+ end
567
+ end
568
+ end
569
+
570
+ namespaced = NamespacedMultipleExample.new
571
+
572
+ namespaced.aasm(:status).current_state
573
+ # => :unapproved
574
+ namespaced.aasm(:review_status).current_state
575
+ # => :unapproved
576
+ namespaced.approve_review
577
+ namespaced.aasm(:review_status).current_state
578
+ # => :approved
579
+ ```
580
+
432
581
  All _AASM_ class- and instance-level `aasm` methods accept a state machine selector.
433
582
  So, for example, to use inspection on a class level, you have to use
434
583
 
435
584
  ```ruby
436
- SimpleMultipleExample.aasm(:work).states
585
+ SimpleMultipleExample.aasm(:move).states.map(&:name)
437
586
  # => [:standing, :walking, :running]
438
587
  ```
439
588
 
@@ -445,26 +594,26 @@ class Example
445
594
  include AASM
446
595
 
447
596
  aasm(:work) do
448
- state :sleeping, :initial => true
597
+ state :sleeping, initial: true
449
598
  state :processing
450
599
 
451
600
  event :start do
452
- transitions :from => :sleeping, :to => :processing
601
+ transitions from: :sleeping, to: :processing
453
602
  end
454
603
  event :stop do
455
- transitions :from => :processing, :to => :sleeping
604
+ transitions from: :processing, to: :sleeping
456
605
  end
457
606
  end
458
607
 
459
608
  aasm(:question) do
460
- state :answered, :initial => true
609
+ state :answered, initial: true
461
610
  state :asked
462
611
 
463
- event :ask, :binding_event => :start do
464
- transitions :from => :answered, :to => :asked
612
+ event :ask, binding_event: :start do
613
+ transitions from: :answered, to: :asked
465
614
  end
466
- event :answer, :binding_event => :stop do
467
- transitions :from => :asked, :to => :answered
615
+ event :answer, binding_event: :stop do
616
+ transitions from: :asked, to: :answered
468
617
  end
469
618
  end
470
619
  end
@@ -510,7 +659,7 @@ class CustomAASMBase < AASM::Base
510
659
  # A custom transiton that we want available across many AASM models.
511
660
  def count_transitions!
512
661
  klass.class_eval do
513
- aasm :with_klass => CustomAASMBase do
662
+ aasm with_klass: CustomAASMBase do
514
663
  after_all_transitions :increment_transition_count
515
664
  end
516
665
  end
@@ -540,26 +689,26 @@ class CustomAASMBase < AASM::Base
540
689
  end
541
690
  ```
542
691
 
543
- When we declare our model that has an AASM state machine, we simply declare the AASM block with a `:with` key to our own class.
692
+ When we declare our model that has an AASM state machine, we simply declare the AASM block with a `:with_klass` key to our own class.
544
693
 
545
694
  ```ruby
546
695
  class SimpleCustomExample
547
696
  include AASM
548
697
 
549
698
  # Let's build an AASM state machine with our custom class.
550
- aasm :with_klass => CustomAASMBase do
699
+ aasm with_klass: CustomAASMBase do
551
700
  requires_guards!
552
701
  count_transitions!
553
702
 
554
- state :initialised, :initial => true
703
+ state :initialised, initial: true
555
704
  state :filled_out
556
705
  state :authorised
557
706
 
558
707
  event :fill_out do
559
- transitions :from => :initialised, :to => :filled_out, :guard => :fillable?
708
+ transitions from: :initialised, to: :filled_out, guard: :fillable?
560
709
  end
561
710
  event :authorise do
562
- transitions :from => :filled_out, :to => :authorised, :guard => :authorizable?
711
+ transitions from: :filled_out, to: :authorised, guard: :authorizable?
563
712
  end
564
713
  end
565
714
  end
@@ -571,20 +720,22 @@ end
571
720
  AASM comes with support for ActiveRecord and allows automatic persisting of the object's
572
721
  state in the database.
573
722
 
723
+ Add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile.
724
+
574
725
  ```ruby
575
726
  class Job < ActiveRecord::Base
576
727
  include AASM
577
728
 
578
729
  aasm do # default column: aasm_state
579
- state :sleeping, :initial => true
730
+ state :sleeping, initial: true
580
731
  state :running
581
732
 
582
733
  event :run do
583
- transitions :from => :sleeping, :to => :running
734
+ transitions from: :sleeping, to: :running
584
735
  end
585
736
 
586
737
  event :sleep do
587
- transitions :from => :running, :to => :sleeping
738
+ transitions from: :running, to: :sleeping
588
739
  end
589
740
  end
590
741
 
@@ -599,11 +750,15 @@ You can tell AASM to auto-save the object or leave it unsaved
599
750
  job = Job.new
600
751
  job.run # not saved
601
752
  job.run! # saved
753
+
754
+ # or
755
+ job.aasm.fire(:run) # not saved
756
+ job.aasm.fire!(:run) # saved
602
757
  ```
603
758
 
604
759
  Saving includes running all validations on the `Job` class. If
605
760
  `whiny_persistence` flag is set to `true`, exception is raised in case of
606
- failure. If `whiny_persistence` flag is set to false, methods with a bang return
761
+ failure. If `whiny_persistence` flag is set to `false`, methods with a bang return
607
762
  `true` if the state transition is successful or `false` if an error occurs.
608
763
 
609
764
  If you want make sure the state gets saved without running validations (and
@@ -615,22 +770,30 @@ be updated in the database (just like ActiveRecord `update_column` is working).
615
770
  class Job < ActiveRecord::Base
616
771
  include AASM
617
772
 
618
- aasm :skip_validation_on_save => true do
619
- state :sleeping, :initial => true
773
+ aasm skip_validation_on_save: true do
774
+ state :sleeping, initial: true
620
775
  state :running
621
776
 
622
777
  event :run do
623
- transitions :from => :sleeping, :to => :running
778
+ transitions from: :sleeping, to: :running
624
779
  end
625
780
 
626
781
  event :sleep do
627
- transitions :from => :running, :to => :sleeping
782
+ transitions from: :running, to: :sleeping
628
783
  end
629
784
  end
630
785
 
631
786
  end
632
787
  ```
633
788
 
789
+ Also, you can skip the validation at instance level with `some_event_name_without_validation!` method.
790
+ With this you have the flexibility of having validation for all your transitions by default and then skip it wherever required.
791
+ Please note that only state column will be updated as mentioned in the above example.
792
+
793
+ ```ruby
794
+ job.run_without_validation!
795
+ ```
796
+
634
797
  If you want to make sure that the _AASM_ column for storing the state is not directly assigned,
635
798
  configure _AASM_ to not allow direct assignment, like this:
636
799
 
@@ -638,12 +801,12 @@ configure _AASM_ to not allow direct assignment, like this:
638
801
  class Job < ActiveRecord::Base
639
802
  include AASM
640
803
 
641
- aasm :no_direct_assignment => true do
642
- state :sleeping, :initial => true
804
+ aasm no_direct_assignment: true do
805
+ state :sleeping, initial: true
643
806
  state :running
644
807
 
645
808
  event :run do
646
- transitions :from => :sleeping, :to => :running
809
+ transitions from: :sleeping, to: :running
647
810
  end
648
811
  end
649
812
 
@@ -659,6 +822,37 @@ job.aasm_state = :running # => raises AASM::NoDirectAssignmentError
659
822
  job.aasm_state # => 'sleeping'
660
823
  ```
661
824
 
825
+ ### Timestamps
826
+
827
+ You can tell _AASM_ to try to write a timestamp whenever a new state is entered.
828
+ If `timestamps: true` is set, _AASM_ will look for a field named like the new state plus `_at` and try to fill it:
829
+
830
+ ```ruby
831
+ class Job < ActiveRecord::Base
832
+ include AASM
833
+
834
+ aasm timestamps: true do
835
+ state :sleeping, initial: true
836
+ state :running
837
+
838
+ event :run do
839
+ transitions from: :sleeping, to: :running
840
+ end
841
+ end
842
+ end
843
+ ```
844
+
845
+ resulting in this:
846
+
847
+ ```ruby
848
+ job = Job.create
849
+ job.running_at # => nil
850
+ job.run!
851
+ job.running_at # => 2020-02-20 20:00:00
852
+ ```
853
+
854
+ Missing timestamp fields are silently ignored, so it is not necessary to have setters (such as ActiveRecord columns) for *all* states when using this option.
855
+
662
856
  #### ActiveRecord enums
663
857
 
664
858
  You can use
@@ -674,8 +868,8 @@ class Job < ActiveRecord::Base
674
868
  running: 99
675
869
  }
676
870
 
677
- aasm :column => :state, :enum => true do
678
- state :sleeping, :initial => true
871
+ aasm column: :state, enum: true do
872
+ state :sleeping, initial: true
679
873
  state :running
680
874
  end
681
875
  end
@@ -731,6 +925,23 @@ class Job
731
925
  end
732
926
  ```
733
927
 
928
+ ### NoBrainer
929
+
930
+ AASM also supports persistence to [RethinkDB](https://www.rethinkdb.com/)
931
+ if you're using [Nobrainer](http://nobrainer.io/).
932
+ Make sure to include NoBrainer::Document before you include AASM.
933
+
934
+ ```ruby
935
+ class Job
936
+ include NoBrainer::Document
937
+ include AASM
938
+ field :aasm_state
939
+ aasm do
940
+ ...
941
+ end
942
+ end
943
+ ```
944
+
734
945
  ### Redis
735
946
 
736
947
  AASM also supports persistence in Redis via
@@ -757,7 +968,7 @@ class Job < ActiveRecord::Base
757
968
  include AASM
758
969
 
759
970
  aasm do
760
- state :sleeping, :initial => true
971
+ state :sleeping, initial: true
761
972
  state :running
762
973
  state :cleaning
763
974
  end
@@ -786,8 +997,8 @@ defining the `AASM` states, like this:
786
997
  class Job < ActiveRecord::Base
787
998
  include AASM
788
999
 
789
- aasm :create_scopes => false do
790
- state :sleeping, :initial => true
1000
+ aasm create_scopes: false do
1001
+ state :sleeping, initial: true
791
1002
  state :running
792
1003
  state :cleaning
793
1004
  end
@@ -820,11 +1031,11 @@ class Job < ActiveRecord::Base
820
1031
  include AASM
821
1032
 
822
1033
  aasm do
823
- state :sleeping, :initial => true
1034
+ state :sleeping, initial: true
824
1035
  state :running
825
1036
 
826
- event :run, :after_commit => :notify_about_running_job do
827
- transitions :from => :sleeping, :to => :running
1037
+ event :run, after_commit: :notify_about_running_job do
1038
+ transitions from: :sleeping, to: :running
828
1039
  end
829
1040
  end
830
1041
 
@@ -846,18 +1057,24 @@ job.run
846
1057
  job.save! #notify_about_running_job is not run
847
1058
  ```
848
1059
 
1060
+ Please note that `:after_commit` AASM callbacks behaves around custom implementation
1061
+ of transaction pattern rather than a real-life DB transaction. This fact still causes
1062
+ the race conditions and redundant callback calls within nested transaction. In order
1063
+ to fix that it's highly recommended to add `gem 'after_commit_everywhere', '~> 1.0'`
1064
+ to your `Gemfile`.
1065
+
849
1066
  If you want to encapsulate state changes within an own transaction, the behavior
850
1067
  of this nested transaction might be confusing. Take a look at
851
1068
  [ActiveRecord Nested Transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)
852
1069
  if you want to know more about this. Nevertheless, AASM by default requires a new transaction
853
- `transaction(:requires_new => true)`. You can override this behavior by changing
1070
+ `transaction(requires_new: true)`. You can override this behavior by changing
854
1071
  the configuration
855
1072
 
856
1073
  ```ruby
857
1074
  class Job < ActiveRecord::Base
858
1075
  include AASM
859
1076
 
860
- aasm :requires_new_transaction => false do
1077
+ aasm requires_new_transaction: false do
861
1078
  ...
862
1079
  end
863
1080
 
@@ -865,11 +1082,29 @@ class Job < ActiveRecord::Base
865
1082
  end
866
1083
  ```
867
1084
 
868
- which then leads to `transaction(:requires_new => false)`, the Rails default.
1085
+ which then leads to `transaction(requires_new: false)`, the Rails default.
1086
+
1087
+ Additionally, if you do not want any of your ActiveRecord actions to be
1088
+ wrapped in a transaction, you can specify the `use_transactions` flag. This can
1089
+ be useful if you want want to persist things to the database that happen as a
1090
+ result of a transaction or callback, even when some error occurs. The
1091
+ `use_transactions` flag is true by default.
1092
+
1093
+ ```ruby
1094
+ class Job < ActiveRecord::Base
1095
+ include AASM
1096
+
1097
+ aasm use_transactions: false do
1098
+ ...
1099
+ end
1100
+
1101
+ ...
1102
+ end
1103
+ ```
869
1104
 
870
1105
  ### Pessimistic Locking
871
1106
 
872
- AASM supports [Active Record pessimistic locking via `with_lock`](http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html#method-i-with_lock) for database persistence layers.
1107
+ AASM supports [ActiveRecord pessimistic locking via `with_lock`](http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html#method-i-with_lock) for database persistence layers.
873
1108
 
874
1109
  | Option | Purpose |
875
1110
  | ------ | ------- |
@@ -882,7 +1117,7 @@ AASM supports [Active Record pessimistic locking via `with_lock`](http://api.rub
882
1117
  class Job < ActiveRecord::Base
883
1118
  include AASM
884
1119
 
885
- aasm :requires_lock => true do
1120
+ aasm requires_lock: true do
886
1121
  ...
887
1122
  end
888
1123
 
@@ -894,7 +1129,7 @@ end
894
1129
  class Job < ActiveRecord::Base
895
1130
  include AASM
896
1131
 
897
- aasm :requires_lock => 'FOR UPDATE NOWAIT' do
1132
+ aasm requires_lock: 'FOR UPDATE NOWAIT' do
898
1133
  ...
899
1134
  end
900
1135
 
@@ -912,18 +1147,21 @@ this by defining your favorite column name, using `:column` like this:
912
1147
  class Job < ActiveRecord::Base
913
1148
  include AASM
914
1149
 
915
- aasm :column => 'my_state' do
1150
+ aasm column: :my_state do
916
1151
  ...
917
1152
  end
918
1153
 
919
- aasm :another_state_machine, column: 'second_state' do
1154
+ aasm :another_state_machine, column: :second_state do
920
1155
  ...
921
1156
  end
922
1157
  end
923
1158
  ```
924
1159
 
925
1160
  Whatever column name is used, make sure to add a migration to provide this column
926
- (of type `string`):
1161
+ (of type `string`).
1162
+ Do not add default value for column at the database level. If you add default
1163
+ value in database then AASM callbacks on the initial state will not be fired upon
1164
+ instantiation of the model.
927
1165
 
928
1166
  ```ruby
929
1167
  class AddJobState < ActiveRecord::Migration
@@ -937,6 +1175,13 @@ class AddJobState < ActiveRecord::Migration
937
1175
  end
938
1176
  ```
939
1177
 
1178
+ ### Log State Changes
1179
+
1180
+ Logging state change can be done using [paper_trail](https://github.com/paper-trail-gem/paper_trail) gem
1181
+
1182
+ Example of implementation can be found here [https://github.com/nitsujri/aasm-papertrail-example](https://github.com/nitsujri/aasm-papertrail-example)
1183
+
1184
+
940
1185
  ### Inspection
941
1186
 
942
1187
  AASM supports query methods for states and events
@@ -948,19 +1193,19 @@ class Job
948
1193
  include AASM
949
1194
 
950
1195
  aasm do
951
- state :sleeping, :initial => true
1196
+ state :sleeping, initial: true
952
1197
  state :running, :cleaning
953
1198
 
954
1199
  event :run do
955
- transitions :from => :sleeping, :to => :running
1200
+ transitions from: :sleeping, to: :running
956
1201
  end
957
1202
 
958
1203
  event :clean do
959
- transitions :from => :running, :to => :cleaning, :guard => :cleaning_needed?
1204
+ transitions from: :running, to: :cleaning, guard: :cleaning_needed?
960
1205
  end
961
1206
 
962
1207
  event :sleep do
963
- transitions :from => [:running, :cleaning], :to => :sleeping
1208
+ transitions from: [:running, :cleaning], to: :sleeping
964
1209
  end
965
1210
  end
966
1211
 
@@ -978,15 +1223,19 @@ Job.aasm.states.map(&:name)
978
1223
  job = Job.new
979
1224
 
980
1225
  # show all permitted states (from initial state)
981
- job.aasm.states(:permitted => true).map(&:name)
1226
+ job.aasm.states(permitted: true).map(&:name)
982
1227
  #=> [:running]
983
1228
 
1229
+ # List all the permitted transitions(event and state pairs) from initial state
1230
+ job.aasm.permitted_transitions
1231
+ #=> [{ :event => :run, :state => :running }]
1232
+
984
1233
  job.run
985
- job.aasm.states(:permitted => true).map(&:name)
1234
+ job.aasm.states(permitted: true).map(&:name)
986
1235
  #=> [:sleeping]
987
1236
 
988
1237
  # show all non permitted states
989
- job.aasm.states(:permitted => false).map(&:name)
1238
+ job.aasm.states(permitted: false).map(&:name)
990
1239
  #=> [:cleaning]
991
1240
 
992
1241
  # show all possible (triggerable) events from the current state
@@ -994,23 +1243,23 @@ job.aasm.events.map(&:name)
994
1243
  #=> [:clean, :sleep]
995
1244
 
996
1245
  # show all permitted events
997
- job.aasm.events(:permitted => true).map(&:name)
1246
+ job.aasm.events(permitted: true).map(&:name)
998
1247
  #=> [:sleep]
999
1248
 
1000
1249
  # show all non permitted events
1001
- job.aasm.events(:permitted => false).map(&:name)
1250
+ job.aasm.events(permitted: false).map(&:name)
1002
1251
  #=> [:clean]
1003
1252
 
1004
1253
  # show all possible events except a specific one
1005
- job.aasm.events(:reject => :sleep).map(&:name)
1254
+ job.aasm.events(reject: :sleep).map(&:name)
1006
1255
  #=> [:clean]
1007
1256
 
1008
1257
  # list states for select
1009
1258
  Job.aasm.states_for_select
1010
- => [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
1259
+ #=> [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
1011
1260
 
1012
1261
  # show permitted states with guard parameter
1013
- job.aasm.states({:permitted => true}, guard_parameter).map(&:name)
1262
+ job.aasm.states({permitted: true}, guard_parameter).map(&:name)
1014
1263
  ```
1015
1264
 
1016
1265
 
@@ -1023,7 +1272,7 @@ use
1023
1272
  class Job
1024
1273
  include AASM
1025
1274
 
1026
- aasm :logger => Rails.logger do
1275
+ aasm logger: Rails.logger do
1027
1276
  ...
1028
1277
  end
1029
1278
  end
@@ -1047,7 +1296,15 @@ the 'instance method symbol / string' way whenever possible when defining guardi
1047
1296
 
1048
1297
  #### RSpec
1049
1298
 
1050
- AASM provides some matchers for [RSpec](http://rspec.info): `transition_from`, `have_state`, `allow_event` and `allow_transition_to`. Add `require 'aasm/rspec'` to your `spec_helper.rb` file and use them like this:
1299
+ AASM provides some matchers for [RSpec](http://rspec.info):
1300
+ * `transition_from`,
1301
+ * `have_state`, `allow_event`
1302
+ * and `allow_transition_to`.
1303
+
1304
+ ##### Installation Instructions:
1305
+ * Add `require 'aasm/rspec'` to your `spec_helper.rb` file.
1306
+
1307
+ ##### Examples Of Usage in Rspec:
1051
1308
 
1052
1309
  ```ruby
1053
1310
  # classes with only the default state machine
@@ -1060,7 +1317,7 @@ expect(job).to allow_event :run
1060
1317
  expect(job).to_not allow_event :clean
1061
1318
  expect(job).to allow_transition_to(:running)
1062
1319
  expect(job).to_not allow_transition_to(:cleaning)
1063
- # on_event also accept arguments
1320
+ # on_event also accept multiple arguments
1064
1321
  expect(job).to transition_from(:sleeping).to(:running).on_event(:run, :defragmentation)
1065
1322
 
1066
1323
  # classes with multiple state machine
@@ -1081,6 +1338,9 @@ expect(multiple).to allow_event(:start).on(:move)
1081
1338
  expect(multiple).to_not allow_event(:stop).on(:move)
1082
1339
  expect(multiple).to allow_transition_to(:processing).on(:move)
1083
1340
  expect(multiple).to_not allow_transition_to(:sleeping).on(:move)
1341
+ # allow_event also accepts arguments
1342
+ expect(job).to allow_event(:run).with(:defragmentation)
1343
+
1084
1344
  ```
1085
1345
 
1086
1346
  #### Minitest
@@ -1091,7 +1351,10 @@ AASM provides assertions and rspec-like expectations for [Minitest](https://gith
1091
1351
 
1092
1352
  List of supported assertions: `assert_have_state`, `refute_have_state`, `assert_transitions_from`, `refute_transitions_from`, `assert_event_allowed`, `refute_event_allowed`, `assert_transition_to_allowed`, `refute_transition_to_allowed`.
1093
1353
 
1094
- Add `require 'aasm/minitest' to your `test_helper.rb` file and use them like this:
1354
+
1355
+ ##### Examples Of Usage (Minitest):
1356
+
1357
+ Add `require 'aasm/minitest'` to your `test_helper.rb` file and use them like this:
1095
1358
 
1096
1359
  ```ruby
1097
1360
  # classes with only the default state machine
@@ -1198,7 +1461,15 @@ After installing AASM you can run generator:
1198
1461
  ```
1199
1462
  Replace NAME with the Model name, COLUMN_NAME is optional(default is 'aasm_state').
1200
1463
  This will create a model (if one does not exist) and configure it with aasm block.
1201
- For Active record orm a migration file is added to add aasm state column to table.
1464
+ For ActiveRecord orm a migration file is added to add aasm state column to table.
1465
+
1466
+ ### Docker
1467
+
1468
+ Run test suite easily on docker
1469
+ ```
1470
+ 1. docker-compose build aasm
1471
+ 2. docker-compose run --rm aasm
1472
+ ```
1202
1473
 
1203
1474
  ## Latest changes ##
1204
1475
 
@@ -1220,6 +1491,12 @@ Feel free to
1220
1491
  * [Anil Maurya](http://github.com/anilmaurya) (since 2016)
1221
1492
 
1222
1493
 
1494
+
1495
+ ## Stargazers over time
1496
+
1497
+ [![Stargazers over time](https://starchart.cc/aasm/aasm.svg)](https://starchart.cc/aasm/aasm)
1498
+
1499
+
1223
1500
  ## [Contributing](CONTRIBUTING.md)
1224
1501
 
1225
1502
  ## Warranty ##
@@ -1231,7 +1508,7 @@ purpose.
1231
1508
 
1232
1509
  ## License ##
1233
1510
 
1234
- Copyright (c) 2006-2016 Scott Barron
1511
+ Copyright (c) 2006-2017 Scott Barron
1235
1512
 
1236
1513
  Permission is hereby granted, free of charge, to any person obtaining
1237
1514
  a copy of this software and associated documentation files (the