aasm 4.12.3 → 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/README.md +284 -119
  3. data/lib/aasm/aasm.rb +30 -27
  4. data/lib/aasm/base.rb +61 -11
  5. data/lib/aasm/configuration.rb +3 -0
  6. data/lib/aasm/core/event.rb +26 -30
  7. data/lib/aasm/core/invoker.rb +129 -0
  8. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  9. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  10. data/lib/aasm/core/invokers/literal_invoker.rb +49 -0
  11. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  12. data/lib/aasm/core/state.rb +16 -14
  13. data/lib/aasm/core/transition.rb +8 -69
  14. data/lib/aasm/dsl_helper.rb +24 -22
  15. data/lib/aasm/errors.rb +5 -3
  16. data/lib/aasm/instance_base.rb +28 -5
  17. data/lib/aasm/localizer.rb +13 -3
  18. data/lib/aasm/persistence/active_record_persistence.rb +25 -5
  19. data/lib/aasm/persistence/base.rb +14 -3
  20. data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
  21. data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
  22. data/lib/aasm/persistence/mongoid_persistence.rb +1 -1
  23. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  24. data/lib/aasm/persistence/orm.rb +23 -19
  25. data/lib/aasm/persistence/plain_persistence.rb +2 -1
  26. data/lib/aasm/persistence/redis_persistence.rb +1 -1
  27. data/lib/aasm/persistence/sequel_persistence.rb +0 -1
  28. data/lib/aasm/persistence.rb +3 -0
  29. data/lib/aasm/rspec/allow_event.rb +5 -1
  30. data/lib/aasm/rspec/allow_transition_to.rb +5 -1
  31. data/lib/aasm/rspec/transition_from.rb +5 -1
  32. data/lib/aasm/version.rb +1 -1
  33. data/lib/aasm.rb +5 -2
  34. data/lib/generators/aasm/orm_helpers.rb +7 -1
  35. data/lib/generators/active_record/aasm_generator.rb +3 -1
  36. data/lib/generators/active_record/templates/migration.rb +1 -1
  37. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  38. data/lib/motion-aasm.rb +1 -0
  39. metadata +42 -344
  40. data/.document +0 -6
  41. data/.gitignore +0 -20
  42. data/.travis.yml +0 -52
  43. data/API +0 -34
  44. data/Appraisals +0 -43
  45. data/CHANGELOG.md +0 -370
  46. data/CODE_OF_CONDUCT.md +0 -13
  47. data/CONTRIBUTING.md +0 -24
  48. data/Gemfile +0 -7
  49. data/Gemfile.lock_old +0 -151
  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 -124
  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 -94
  174. data/spec/unit/complex_multiple_example_spec.rb +0 -115
  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 -735
  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,8 +2,8 @@
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
7
 
8
8
  ## Index
9
9
  - [Upgrade from version 3 to 4](#upgrade-from-version-3-to-4)
@@ -20,15 +20,18 @@
20
20
  - [Extending AASM](#extending-aasm)
21
21
  - [ActiveRecord](#activerecord)
22
22
  - [Bang events](#bang-events)
23
+ - [Timestamps](#timestamps)
23
24
  - [ActiveRecord enums](#activerecord-enums)
24
25
  - [Sequel](#sequel)
25
26
  - [Dynamoid](#dynamoid)
26
27
  - [Mongoid](#mongoid)
28
+ - [Nobrainer](#nobrainer)
27
29
  - [Redis](#redis)
28
30
  - [Automatic Scopes](#automatic-scopes)
29
31
  - [Transaction support](#transaction-support)
30
32
  - [Pessimistic Locking](#pessimistic-locking)
31
33
  - [Column name & migration](#column-name--migration)
34
+ - [Log State Changes](#log-state-changes)
32
35
  - [Inspection](#inspection)
33
36
  - [Warning output](#warning-output)
34
37
  - [RubyMotion support](#rubymotion-support)
@@ -42,6 +45,7 @@
42
45
  - [Bundler](#or-if-you-are-using-bundler)
43
46
  - [Building your own gems](#building-your-own-gems)
44
47
  - [Generators](#generators)
48
+ - [Test suite with Docker](#docker)
45
49
  - [Latest changes](#latest-changes)
46
50
  - [Questions?](#questions)
47
51
  - [Maintainers](#maintainers)
@@ -52,10 +56,8 @@
52
56
  This package contains AASM, a library for adding finite state machines to Ruby classes.
53
57
 
54
58
  AASM started as the *acts_as_state_machine* plugin but has evolved into a more generic library
55
- that no longer targets only ActiveRecord models. It currently provides adapters for
56
- [ActiveRecord](http://api.rubyonrails.org/classes/ActiveRecord/Base.html),
57
- and [Mongoid](http://mongoid.org/) but it can be used for any Ruby class, no matter what
58
- 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).
59
61
 
60
62
  ## Upgrade from version 3 to 4
61
63
 
@@ -71,19 +73,19 @@ class Job
71
73
  include AASM
72
74
 
73
75
  aasm do
74
- state :sleeping, :initial => true
76
+ state :sleeping, initial: true
75
77
  state :running, :cleaning
76
78
 
77
79
  event :run do
78
- transitions :from => :sleeping, :to => :running
80
+ transitions from: :sleeping, to: :running
79
81
  end
80
82
 
81
83
  event :clean do
82
- transitions :from => :running, :to => :cleaning
84
+ transitions from: :running, to: :cleaning
83
85
  end
84
86
 
85
87
  event :sleep do
86
- transitions :from => [:running, :cleaning], :to => :sleeping
88
+ transitions from: [:running, :cleaning], to: :sleeping
87
89
  end
88
90
  end
89
91
 
@@ -109,7 +111,7 @@ AASM not to be *whiny*:
109
111
  ```ruby
110
112
  class Job
111
113
  ...
112
- aasm :whiny_transitions => false do
114
+ aasm whiny_transitions: false do
113
115
  ...
114
116
  end
115
117
  end
@@ -130,27 +132,27 @@ the transition succeeds :
130
132
 
131
133
  ### Callbacks
132
134
 
133
- You can define a number of callbacks for your transitions. These methods will be
134
- 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:
135
137
 
136
138
  ```ruby
137
139
  class Job
138
140
  include AASM
139
141
 
140
142
  aasm do
141
- state :sleeping, :initial => true, :before_enter => :do_something
142
- state :running
143
+ state :sleeping, initial: true, before_enter: :do_something
144
+ state :running, before_enter: Proc.new { do_something && notify_somebody }
143
145
  state :finished
144
146
 
145
147
  after_all_transitions :log_status_change
146
148
 
147
- event :run, :after => :notify_somebody do
149
+ event :run, after: :notify_somebody do
148
150
  before do
149
151
  log('Preparing to run')
150
152
  end
151
153
 
152
- transitions :from => :sleeping, :to => :running, :after => Proc.new {|*args| set_process(*args) }
153
- 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
154
156
  end
155
157
 
156
158
  event :sleep do
@@ -160,7 +162,7 @@ class Job
160
162
  error do |e|
161
163
  ...
162
164
  end
163
- transitions :from => :running, :to => :sleeping
165
+ transitions from: :running, to: :sleeping
164
166
  end
165
167
  end
166
168
 
@@ -195,6 +197,8 @@ is finished.
195
197
 
196
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:
197
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
+
198
202
  ```ruby
199
203
  class LogRunTime
200
204
  # optional args parameter can be omitted, but if you define initialize
@@ -209,23 +213,34 @@ class LogRunTime
209
213
  end
210
214
  ```
211
215
 
212
- Also, you can pass parameters to events:
216
+ #### Parameters
217
+ You can pass parameters to events:
213
218
 
214
219
  ```ruby
215
220
  job = Job.new
216
- job.run(:running, :defragmentation)
221
+ job.run(:defragmentation)
217
222
  ```
218
223
 
219
- 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.
220
226
 
221
- 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
222
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
223
238
  In case of an error during the event processing the error is rescued and passed to `:error`
224
239
  callback, which can handle it or re-raise it for further propagation.
225
240
 
226
241
  Also, you can define a method that will be called if any event fails:
227
242
 
228
- ```
243
+ ```ruby
229
244
  def aasm_event_failed(event_name, old_state_name)
230
245
  # use custom exception/messages, report metrics, etc
231
246
  end
@@ -259,8 +274,8 @@ begin
259
274
  new_state enter
260
275
  ...update state...
261
276
  event before_success # if persist successful
262
- transition success # if persist successful
263
- 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
264
279
  old_state after_exit
265
280
  new_state after_enter
266
281
  event after
@@ -274,6 +289,8 @@ ensure
274
289
  end
275
290
  ```
276
291
 
292
+ Use event's `after_commit` callback if it should be fired after database update.
293
+
277
294
  #### The current event triggered
278
295
 
279
296
  While running the callbacks you can easily retrieve the name of the event triggered
@@ -304,31 +321,31 @@ and then
304
321
  Let's assume you want to allow particular transitions only if a defined condition is
305
322
  given. For this you can set up a guard per transition, which will run before actually
306
323
  running the transition. If the guard returns `false` the transition will be
307
- denied (raising `AASM::InvalidTransition` or returning `false` itself):
324
+ denied (raising `AASM::InvalidTransition`):
308
325
 
309
326
  ```ruby
310
327
  class Cleaner
311
328
  include AASM
312
329
 
313
330
  aasm do
314
- state :idle, :initial => true
331
+ state :idle, initial: true
315
332
  state :cleaning
316
333
 
317
334
  event :clean do
318
- transitions :from => :idle, :to => :cleaning, :guard => :cleaning_needed?
335
+ transitions from: :idle, to: :cleaning, guard: :cleaning_needed?
319
336
  end
320
337
 
321
338
  event :clean_if_needed do
322
- transitions :from => :idle, :to => :cleaning do
339
+ transitions from: :idle, to: :cleaning do
323
340
  guard do
324
341
  cleaning_needed?
325
342
  end
326
343
  end
327
- transitions :from => :idle, :to => :idle
344
+ transitions from: :idle, to: :idle
328
345
  end
329
346
 
330
347
  event :clean_if_dirty do
331
- transitions :from => :idle, :to => :cleaning, :guard => :if_dirty?
348
+ transitions from: :idle, to: :cleaning, guard: :if_dirty?
332
349
  end
333
350
  end
334
351
 
@@ -347,7 +364,7 @@ job.clean # => raises AASM::InvalidTransition
347
364
  job.may_clean_if_needed? # => true
348
365
  job.clean_if_needed! # idle
349
366
 
350
- job.clean_if_dirty(:clean) # => false
367
+ job.clean_if_dirty(:clean) # => raises AASM::InvalidTransition
351
368
  job.clean_if_dirty(:dirty) # => true
352
369
  ```
353
370
 
@@ -357,16 +374,16 @@ You can even provide a number of guards, which all have to succeed to proceed
357
374
  def walked_the_dog?; ...; end
358
375
 
359
376
  event :sleep do
360
- transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?, :walked_the_dog?]
377
+ transitions from: :running, to: :sleeping, guards: [:cleaning_needed?, :walked_the_dog?]
361
378
  end
362
379
  ```
363
380
 
364
381
  If you want to provide guards for all transitions within an event, you can use event guards
365
382
 
366
383
  ```ruby
367
- event :sleep, :guards => [:walked_the_dog?] do
368
- transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?]
369
- 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
370
387
  end
371
388
  ```
372
389
 
@@ -374,15 +391,30 @@ If you prefer a more Ruby-like guard syntax, you can use `if` and `unless` as we
374
391
 
375
392
  ```ruby
376
393
  event :clean do
377
- transitions :from => :running, :to => :cleaning, :if => :cleaning_needed?
394
+ transitions from: :running, to: :cleaning, if: :cleaning_needed?
378
395
  end
379
396
 
380
397
  event :sleep do
381
- transitions :from => :running, :to => :sleeping, :unless => :cleaning_needed?
398
+ transitions from: :running, to: :sleeping, unless: :cleaning_needed?
382
399
  end
383
400
  end
384
401
  ```
385
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
+ ```
386
418
 
387
419
  ### Transitions
388
420
 
@@ -395,7 +427,7 @@ class Job
395
427
  include AASM
396
428
 
397
429
  aasm do
398
- state :stage1, :initial => true
430
+ state :stage1, initial: true
399
431
  state :stage2
400
432
  state :stage3
401
433
  state :completed
@@ -416,40 +448,67 @@ job.stage1_completed
416
448
  job.aasm.current_state # stage3
417
449
  ```
418
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
+ ```
419
478
 
420
479
  ### Multiple state machines per class
421
480
 
422
481
  Multiple state machines per class are supported. Be aware though that _AASM_ has been
423
- 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.
424
483
 
425
484
  ```ruby
426
485
  class SimpleMultipleExample
427
486
  include AASM
428
- aasm(:move) do
429
- state :standing, :initial => true
487
+ aasm(:move, column: 'move_state') do
488
+ state :standing, initial: true
430
489
  state :walking
431
490
  state :running
432
491
 
433
492
  event :walk do
434
- transitions :from => :standing, :to => :walking
493
+ transitions from: :standing, to: :walking
435
494
  end
436
495
  event :run do
437
- transitions :from => [:standing, :walking], :to => :running
496
+ transitions from: [:standing, :walking], to: :running
438
497
  end
439
498
  event :hold do
440
- transitions :from => [:walking, :running], :to => :standing
499
+ transitions from: [:walking, :running], to: :standing
441
500
  end
442
501
  end
443
502
 
444
- aasm(:work) do
445
- state :sleeping, :initial => true
503
+ aasm(:work, column: 'work_state') do
504
+ state :sleeping, initial: true
446
505
  state :processing
447
506
 
448
507
  event :start do
449
- transitions :from => :sleeping, :to => :processing
508
+ transitions from: :sleeping, to: :processing
450
509
  end
451
510
  event :stop do
452
- transitions :from => :processing, :to => :sleeping
511
+ transitions from: :processing, to: :sleeping
453
512
  end
454
513
  end
455
514
  end
@@ -458,13 +517,13 @@ simple = SimpleMultipleExample.new
458
517
 
459
518
  simple.aasm(:move).current_state
460
519
  # => :standing
461
- simple.aasm(:work).current
520
+ simple.aasm(:work).current_state
462
521
  # => :sleeping
463
522
 
464
523
  simple.start
465
524
  simple.aasm(:move).current_state
466
525
  # => :standing
467
- simple.aasm(:work).current
526
+ simple.aasm(:work).current_state
468
527
  # => :processing
469
528
 
470
529
  ```
@@ -482,28 +541,28 @@ Alternatively, you can provide a namespace for each state machine:
482
541
  class NamespacedMultipleExample
483
542
  include AASM
484
543
  aasm(:status) do
485
- state :unapproved, :initial => true
544
+ state :unapproved, initial: true
486
545
  state :approved
487
546
 
488
547
  event :approve do
489
- transitions :from => :unapproved, :to => :approved
548
+ transitions from: :unapproved, to: :approved
490
549
  end
491
550
 
492
551
  event :unapprove do
493
- transitions :from => :approved, :to => :unapproved
552
+ transitions from: :approved, to: :unapproved
494
553
  end
495
554
  end
496
555
 
497
556
  aasm(:review_status, namespace: :review) do
498
- state :unapproved, :initial => true
557
+ state :unapproved, initial: true
499
558
  state :approved
500
559
 
501
560
  event :approve do
502
- transitions :from => :unapproved, :to => :approved
561
+ transitions from: :unapproved, to: :approved
503
562
  end
504
563
 
505
564
  event :unapprove do
506
- transitions :from => :approved, :to => :unapproved
565
+ transitions from: :approved, to: :unapproved
507
566
  end
508
567
  end
509
568
  end
@@ -523,7 +582,7 @@ All _AASM_ class- and instance-level `aasm` methods accept a state machine selec
523
582
  So, for example, to use inspection on a class level, you have to use
524
583
 
525
584
  ```ruby
526
- SimpleMultipleExample.aasm(:work).states
585
+ SimpleMultipleExample.aasm(:move).states.map(&:name)
527
586
  # => [:standing, :walking, :running]
528
587
  ```
529
588
 
@@ -535,26 +594,26 @@ class Example
535
594
  include AASM
536
595
 
537
596
  aasm(:work) do
538
- state :sleeping, :initial => true
597
+ state :sleeping, initial: true
539
598
  state :processing
540
599
 
541
600
  event :start do
542
- transitions :from => :sleeping, :to => :processing
601
+ transitions from: :sleeping, to: :processing
543
602
  end
544
603
  event :stop do
545
- transitions :from => :processing, :to => :sleeping
604
+ transitions from: :processing, to: :sleeping
546
605
  end
547
606
  end
548
607
 
549
608
  aasm(:question) do
550
- state :answered, :initial => true
609
+ state :answered, initial: true
551
610
  state :asked
552
611
 
553
- event :ask, :binding_event => :start do
554
- transitions :from => :answered, :to => :asked
612
+ event :ask, binding_event: :start do
613
+ transitions from: :answered, to: :asked
555
614
  end
556
- event :answer, :binding_event => :stop do
557
- transitions :from => :asked, :to => :answered
615
+ event :answer, binding_event: :stop do
616
+ transitions from: :asked, to: :answered
558
617
  end
559
618
  end
560
619
  end
@@ -600,7 +659,7 @@ class CustomAASMBase < AASM::Base
600
659
  # A custom transiton that we want available across many AASM models.
601
660
  def count_transitions!
602
661
  klass.class_eval do
603
- aasm :with_klass => CustomAASMBase do
662
+ aasm with_klass: CustomAASMBase do
604
663
  after_all_transitions :increment_transition_count
605
664
  end
606
665
  end
@@ -630,26 +689,26 @@ class CustomAASMBase < AASM::Base
630
689
  end
631
690
  ```
632
691
 
633
- 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.
634
693
 
635
694
  ```ruby
636
695
  class SimpleCustomExample
637
696
  include AASM
638
697
 
639
698
  # Let's build an AASM state machine with our custom class.
640
- aasm :with_klass => CustomAASMBase do
699
+ aasm with_klass: CustomAASMBase do
641
700
  requires_guards!
642
701
  count_transitions!
643
702
 
644
- state :initialised, :initial => true
703
+ state :initialised, initial: true
645
704
  state :filled_out
646
705
  state :authorised
647
706
 
648
707
  event :fill_out do
649
- transitions :from => :initialised, :to => :filled_out, :guard => :fillable?
708
+ transitions from: :initialised, to: :filled_out, guard: :fillable?
650
709
  end
651
710
  event :authorise do
652
- transitions :from => :filled_out, :to => :authorised, :guard => :authorizable?
711
+ transitions from: :filled_out, to: :authorised, guard: :authorizable?
653
712
  end
654
713
  end
655
714
  end
@@ -661,20 +720,22 @@ end
661
720
  AASM comes with support for ActiveRecord and allows automatic persisting of the object's
662
721
  state in the database.
663
722
 
723
+ Add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile.
724
+
664
725
  ```ruby
665
726
  class Job < ActiveRecord::Base
666
727
  include AASM
667
728
 
668
729
  aasm do # default column: aasm_state
669
- state :sleeping, :initial => true
730
+ state :sleeping, initial: true
670
731
  state :running
671
732
 
672
733
  event :run do
673
- transitions :from => :sleeping, :to => :running
734
+ transitions from: :sleeping, to: :running
674
735
  end
675
736
 
676
737
  event :sleep do
677
- transitions :from => :running, :to => :sleeping
738
+ transitions from: :running, to: :sleeping
678
739
  end
679
740
  end
680
741
 
@@ -697,7 +758,7 @@ job.aasm.fire!(:run) # saved
697
758
 
698
759
  Saving includes running all validations on the `Job` class. If
699
760
  `whiny_persistence` flag is set to `true`, exception is raised in case of
700
- 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
701
762
  `true` if the state transition is successful or `false` if an error occurs.
702
763
 
703
764
  If you want make sure the state gets saved without running validations (and
@@ -709,22 +770,30 @@ be updated in the database (just like ActiveRecord `update_column` is working).
709
770
  class Job < ActiveRecord::Base
710
771
  include AASM
711
772
 
712
- aasm :skip_validation_on_save => true do
713
- state :sleeping, :initial => true
773
+ aasm skip_validation_on_save: true do
774
+ state :sleeping, initial: true
714
775
  state :running
715
776
 
716
777
  event :run do
717
- transitions :from => :sleeping, :to => :running
778
+ transitions from: :sleeping, to: :running
718
779
  end
719
780
 
720
781
  event :sleep do
721
- transitions :from => :running, :to => :sleeping
782
+ transitions from: :running, to: :sleeping
722
783
  end
723
784
  end
724
785
 
725
786
  end
726
787
  ```
727
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
+
728
797
  If you want to make sure that the _AASM_ column for storing the state is not directly assigned,
729
798
  configure _AASM_ to not allow direct assignment, like this:
730
799
 
@@ -732,12 +801,12 @@ configure _AASM_ to not allow direct assignment, like this:
732
801
  class Job < ActiveRecord::Base
733
802
  include AASM
734
803
 
735
- aasm :no_direct_assignment => true do
736
- state :sleeping, :initial => true
804
+ aasm no_direct_assignment: true do
805
+ state :sleeping, initial: true
737
806
  state :running
738
807
 
739
808
  event :run do
740
- transitions :from => :sleeping, :to => :running
809
+ transitions from: :sleeping, to: :running
741
810
  end
742
811
  end
743
812
 
@@ -753,6 +822,37 @@ job.aasm_state = :running # => raises AASM::NoDirectAssignmentError
753
822
  job.aasm_state # => 'sleeping'
754
823
  ```
755
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
+
756
856
  #### ActiveRecord enums
757
857
 
758
858
  You can use
@@ -768,8 +868,8 @@ class Job < ActiveRecord::Base
768
868
  running: 99
769
869
  }
770
870
 
771
- aasm :column => :state, :enum => true do
772
- state :sleeping, :initial => true
871
+ aasm column: :state, enum: true do
872
+ state :sleeping, initial: true
773
873
  state :running
774
874
  end
775
875
  end
@@ -825,6 +925,23 @@ class Job
825
925
  end
826
926
  ```
827
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
+
828
945
  ### Redis
829
946
 
830
947
  AASM also supports persistence in Redis via
@@ -851,7 +968,7 @@ class Job < ActiveRecord::Base
851
968
  include AASM
852
969
 
853
970
  aasm do
854
- state :sleeping, :initial => true
971
+ state :sleeping, initial: true
855
972
  state :running
856
973
  state :cleaning
857
974
  end
@@ -880,8 +997,8 @@ defining the `AASM` states, like this:
880
997
  class Job < ActiveRecord::Base
881
998
  include AASM
882
999
 
883
- aasm :create_scopes => false do
884
- state :sleeping, :initial => true
1000
+ aasm create_scopes: false do
1001
+ state :sleeping, initial: true
885
1002
  state :running
886
1003
  state :cleaning
887
1004
  end
@@ -914,11 +1031,11 @@ class Job < ActiveRecord::Base
914
1031
  include AASM
915
1032
 
916
1033
  aasm do
917
- state :sleeping, :initial => true
1034
+ state :sleeping, initial: true
918
1035
  state :running
919
1036
 
920
- event :run, :after_commit => :notify_about_running_job do
921
- transitions :from => :sleeping, :to => :running
1037
+ event :run, after_commit: :notify_about_running_job do
1038
+ transitions from: :sleeping, to: :running
922
1039
  end
923
1040
  end
924
1041
 
@@ -940,18 +1057,24 @@ job.run
940
1057
  job.save! #notify_about_running_job is not run
941
1058
  ```
942
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
+
943
1066
  If you want to encapsulate state changes within an own transaction, the behavior
944
1067
  of this nested transaction might be confusing. Take a look at
945
1068
  [ActiveRecord Nested Transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)
946
1069
  if you want to know more about this. Nevertheless, AASM by default requires a new transaction
947
- `transaction(:requires_new => true)`. You can override this behavior by changing
1070
+ `transaction(requires_new: true)`. You can override this behavior by changing
948
1071
  the configuration
949
1072
 
950
1073
  ```ruby
951
1074
  class Job < ActiveRecord::Base
952
1075
  include AASM
953
1076
 
954
- aasm :requires_new_transaction => false do
1077
+ aasm requires_new_transaction: false do
955
1078
  ...
956
1079
  end
957
1080
 
@@ -959,9 +1082,9 @@ class Job < ActiveRecord::Base
959
1082
  end
960
1083
  ```
961
1084
 
962
- which then leads to `transaction(:requires_new => false)`, the Rails default.
1085
+ which then leads to `transaction(requires_new: false)`, the Rails default.
963
1086
 
964
- Additionally, if you do not want any of your active record actions to be
1087
+ Additionally, if you do not want any of your ActiveRecord actions to be
965
1088
  wrapped in a transaction, you can specify the `use_transactions` flag. This can
966
1089
  be useful if you want want to persist things to the database that happen as a
967
1090
  result of a transaction or callback, even when some error occurs. The
@@ -971,7 +1094,7 @@ result of a transaction or callback, even when some error occurs. The
971
1094
  class Job < ActiveRecord::Base
972
1095
  include AASM
973
1096
 
974
- aasm :use_transactions => false do
1097
+ aasm use_transactions: false do
975
1098
  ...
976
1099
  end
977
1100
 
@@ -981,7 +1104,7 @@ end
981
1104
 
982
1105
  ### Pessimistic Locking
983
1106
 
984
- 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.
985
1108
 
986
1109
  | Option | Purpose |
987
1110
  | ------ | ------- |
@@ -994,7 +1117,7 @@ AASM supports [Active Record pessimistic locking via `with_lock`](http://api.rub
994
1117
  class Job < ActiveRecord::Base
995
1118
  include AASM
996
1119
 
997
- aasm :requires_lock => true do
1120
+ aasm requires_lock: true do
998
1121
  ...
999
1122
  end
1000
1123
 
@@ -1006,7 +1129,7 @@ end
1006
1129
  class Job < ActiveRecord::Base
1007
1130
  include AASM
1008
1131
 
1009
- aasm :requires_lock => 'FOR UPDATE NOWAIT' do
1132
+ aasm requires_lock: 'FOR UPDATE NOWAIT' do
1010
1133
  ...
1011
1134
  end
1012
1135
 
@@ -1024,18 +1147,21 @@ this by defining your favorite column name, using `:column` like this:
1024
1147
  class Job < ActiveRecord::Base
1025
1148
  include AASM
1026
1149
 
1027
- aasm :column => 'my_state' do
1150
+ aasm column: :my_state do
1028
1151
  ...
1029
1152
  end
1030
1153
 
1031
- aasm :another_state_machine, column: 'second_state' do
1154
+ aasm :another_state_machine, column: :second_state do
1032
1155
  ...
1033
1156
  end
1034
1157
  end
1035
1158
  ```
1036
1159
 
1037
1160
  Whatever column name is used, make sure to add a migration to provide this column
1038
- (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.
1039
1165
 
1040
1166
  ```ruby
1041
1167
  class AddJobState < ActiveRecord::Migration
@@ -1049,6 +1175,13 @@ class AddJobState < ActiveRecord::Migration
1049
1175
  end
1050
1176
  ```
1051
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
+
1052
1185
  ### Inspection
1053
1186
 
1054
1187
  AASM supports query methods for states and events
@@ -1060,19 +1193,19 @@ class Job
1060
1193
  include AASM
1061
1194
 
1062
1195
  aasm do
1063
- state :sleeping, :initial => true
1196
+ state :sleeping, initial: true
1064
1197
  state :running, :cleaning
1065
1198
 
1066
1199
  event :run do
1067
- transitions :from => :sleeping, :to => :running
1200
+ transitions from: :sleeping, to: :running
1068
1201
  end
1069
1202
 
1070
1203
  event :clean do
1071
- transitions :from => :running, :to => :cleaning, :guard => :cleaning_needed?
1204
+ transitions from: :running, to: :cleaning, guard: :cleaning_needed?
1072
1205
  end
1073
1206
 
1074
1207
  event :sleep do
1075
- transitions :from => [:running, :cleaning], :to => :sleeping
1208
+ transitions from: [:running, :cleaning], to: :sleeping
1076
1209
  end
1077
1210
  end
1078
1211
 
@@ -1090,15 +1223,19 @@ Job.aasm.states.map(&:name)
1090
1223
  job = Job.new
1091
1224
 
1092
1225
  # show all permitted states (from initial state)
1093
- job.aasm.states(:permitted => true).map(&:name)
1226
+ job.aasm.states(permitted: true).map(&:name)
1094
1227
  #=> [:running]
1095
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
+
1096
1233
  job.run
1097
- job.aasm.states(:permitted => true).map(&:name)
1234
+ job.aasm.states(permitted: true).map(&:name)
1098
1235
  #=> [:sleeping]
1099
1236
 
1100
1237
  # show all non permitted states
1101
- job.aasm.states(:permitted => false).map(&:name)
1238
+ job.aasm.states(permitted: false).map(&:name)
1102
1239
  #=> [:cleaning]
1103
1240
 
1104
1241
  # show all possible (triggerable) events from the current state
@@ -1106,23 +1243,23 @@ job.aasm.events.map(&:name)
1106
1243
  #=> [:clean, :sleep]
1107
1244
 
1108
1245
  # show all permitted events
1109
- job.aasm.events(:permitted => true).map(&:name)
1246
+ job.aasm.events(permitted: true).map(&:name)
1110
1247
  #=> [:sleep]
1111
1248
 
1112
1249
  # show all non permitted events
1113
- job.aasm.events(:permitted => false).map(&:name)
1250
+ job.aasm.events(permitted: false).map(&:name)
1114
1251
  #=> [:clean]
1115
1252
 
1116
1253
  # show all possible events except a specific one
1117
- job.aasm.events(:reject => :sleep).map(&:name)
1254
+ job.aasm.events(reject: :sleep).map(&:name)
1118
1255
  #=> [:clean]
1119
1256
 
1120
1257
  # list states for select
1121
1258
  Job.aasm.states_for_select
1122
- => [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
1259
+ #=> [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
1123
1260
 
1124
1261
  # show permitted states with guard parameter
1125
- job.aasm.states({:permitted => true}, guard_parameter).map(&:name)
1262
+ job.aasm.states({permitted: true}, guard_parameter).map(&:name)
1126
1263
  ```
1127
1264
 
1128
1265
 
@@ -1135,7 +1272,7 @@ use
1135
1272
  class Job
1136
1273
  include AASM
1137
1274
 
1138
- aasm :logger => Rails.logger do
1275
+ aasm logger: Rails.logger do
1139
1276
  ...
1140
1277
  end
1141
1278
  end
@@ -1159,7 +1296,15 @@ the 'instance method symbol / string' way whenever possible when defining guardi
1159
1296
 
1160
1297
  #### RSpec
1161
1298
 
1162
- 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:
1163
1308
 
1164
1309
  ```ruby
1165
1310
  # classes with only the default state machine
@@ -1172,7 +1317,7 @@ expect(job).to allow_event :run
1172
1317
  expect(job).to_not allow_event :clean
1173
1318
  expect(job).to allow_transition_to(:running)
1174
1319
  expect(job).to_not allow_transition_to(:cleaning)
1175
- # on_event also accept arguments
1320
+ # on_event also accept multiple arguments
1176
1321
  expect(job).to transition_from(:sleeping).to(:running).on_event(:run, :defragmentation)
1177
1322
 
1178
1323
  # classes with multiple state machine
@@ -1193,6 +1338,9 @@ expect(multiple).to allow_event(:start).on(:move)
1193
1338
  expect(multiple).to_not allow_event(:stop).on(:move)
1194
1339
  expect(multiple).to allow_transition_to(:processing).on(:move)
1195
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
+
1196
1344
  ```
1197
1345
 
1198
1346
  #### Minitest
@@ -1203,7 +1351,10 @@ AASM provides assertions and rspec-like expectations for [Minitest](https://gith
1203
1351
 
1204
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`.
1205
1353
 
1206
- 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:
1207
1358
 
1208
1359
  ```ruby
1209
1360
  # classes with only the default state machine
@@ -1310,7 +1461,15 @@ After installing AASM you can run generator:
1310
1461
  ```
1311
1462
  Replace NAME with the Model name, COLUMN_NAME is optional(default is 'aasm_state').
1312
1463
  This will create a model (if one does not exist) and configure it with aasm block.
1313
- 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
+ ```
1314
1473
 
1315
1474
  ## Latest changes ##
1316
1475
 
@@ -1332,6 +1491,12 @@ Feel free to
1332
1491
  * [Anil Maurya](http://github.com/anilmaurya) (since 2016)
1333
1492
 
1334
1493
 
1494
+
1495
+ ## Stargazers over time
1496
+
1497
+ [![Stargazers over time](https://starchart.cc/aasm/aasm.svg)](https://starchart.cc/aasm/aasm)
1498
+
1499
+
1335
1500
  ## [Contributing](CONTRIBUTING.md)
1336
1501
 
1337
1502
  ## Warranty ##