state_machines 0.20.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +154 -18
  3. data/lib/state_machines/branch.rb +30 -17
  4. data/lib/state_machines/callback.rb +12 -13
  5. data/lib/state_machines/core.rb +0 -1
  6. data/lib/state_machines/error.rb +5 -4
  7. data/lib/state_machines/eval_helpers.rb +178 -49
  8. data/lib/state_machines/event.rb +31 -32
  9. data/lib/state_machines/event_collection.rb +4 -5
  10. data/lib/state_machines/extensions.rb +5 -5
  11. data/lib/state_machines/helper_module.rb +1 -1
  12. data/lib/state_machines/integrations/base.rb +1 -1
  13. data/lib/state_machines/integrations.rb +11 -14
  14. data/lib/state_machines/machine/action_hooks.rb +53 -0
  15. data/lib/state_machines/machine/callbacks.rb +59 -0
  16. data/lib/state_machines/machine/class_methods.rb +25 -11
  17. data/lib/state_machines/machine/configuration.rb +124 -0
  18. data/lib/state_machines/machine/event_methods.rb +59 -0
  19. data/lib/state_machines/machine/helper_generators.rb +125 -0
  20. data/lib/state_machines/machine/integration.rb +70 -0
  21. data/lib/state_machines/machine/parsing.rb +77 -0
  22. data/lib/state_machines/machine/rendering.rb +17 -0
  23. data/lib/state_machines/machine/scoping.rb +44 -0
  24. data/lib/state_machines/machine/state_methods.rb +101 -0
  25. data/lib/state_machines/machine/utilities.rb +85 -0
  26. data/lib/state_machines/machine/validation.rb +39 -0
  27. data/lib/state_machines/machine.rb +75 -619
  28. data/lib/state_machines/machine_collection.rb +18 -14
  29. data/lib/state_machines/macro_methods.rb +2 -2
  30. data/lib/state_machines/matcher.rb +6 -6
  31. data/lib/state_machines/matcher_helpers.rb +1 -1
  32. data/lib/state_machines/node_collection.rb +18 -17
  33. data/lib/state_machines/path.rb +2 -4
  34. data/lib/state_machines/path_collection.rb +2 -3
  35. data/lib/state_machines/state.rb +14 -7
  36. data/lib/state_machines/state_collection.rb +3 -3
  37. data/lib/state_machines/state_context.rb +6 -7
  38. data/lib/state_machines/stdio_renderer.rb +16 -16
  39. data/lib/state_machines/syntax_validator.rb +57 -0
  40. data/lib/state_machines/test_helper.rb +290 -27
  41. data/lib/state_machines/transition.rb +57 -46
  42. data/lib/state_machines/transition_collection.rb +22 -25
  43. data/lib/state_machines/version.rb +1 -1
  44. metadata +23 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5aa5d105c78cb53f15f42e8662dd7f8e0d0d5f8807b88dcbd8b4201f13718384
4
- data.tar.gz: d761cedbe052c5c8829626e0875f54dce064f7156162119b4a040594b439068c
3
+ metadata.gz: fcd04394640ccea1429d2e121a46e2c705f8c16b2987b142858ad2f151c9c287
4
+ data.tar.gz: 58cfb25ff972b1b2802730d9084d3c3b27c59a82e694646ce676e38fc661cbb9
5
5
  SHA512:
6
- metadata.gz: 37398c9ca5f2de7413dfb7a8a467984d0fc4d47f8367ea0747fec6d9c1eaca5a7c3439f37988c02dd8ce27622a9a9e54cf5cc0b2d84404f00f92a862c168bb23
7
- data.tar.gz: 159022534eb3c308bc2f2c8e960f111053631d3e10adafc9ae8156c95a26165f48690c682229a577bdfecf918b335ebe5b6d57e82e095c924585ad8d11b9d1ee
6
+ metadata.gz: c9328eea4f9d8d9e57124571de54bb8f5160a044ef913d3e515bcaac933b7355ccf987c10699c71e94145f44bc1e2387342f350dcbff0100d76a5c1c06645321
7
+ data.tar.gz: 07c7bfad14f7ce103eec5d6dfa48a9117bc0a73cb5433447c4bf7b6cdea1b87b894a12ad6b85b5a0cb05d63dd68e291f980eeca40e60754c13d5b5c44a7fcf29
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  ![Build Status](https://github.com/state-machines/state_machines/actions/workflows/ruby.yml/badge.svg)
2
+
2
3
  # State Machines
3
4
 
4
5
  State Machines adds support for creating state machines for attributes on any Ruby class.
@@ -9,15 +10,21 @@ State Machines adds support for creating state machines for attributes on any Ru
9
10
 
10
11
  Add this line to your application's Gemfile:
11
12
 
12
- gem 'state_machines'
13
+ ```ruby
14
+ gem 'state_machines'
15
+ ```
13
16
 
14
17
  And then execute:
15
18
 
16
- $ bundle
19
+ ```sh
20
+ bundle
21
+ ```
17
22
 
18
23
  Or install it yourself as:
19
24
 
20
- $ gem install state_machines
25
+ ```sh
26
+ gem install state_machines
27
+ ```
21
28
 
22
29
  ## Usage
23
30
 
@@ -38,11 +45,11 @@ Class definition:
38
45
 
39
46
  ```ruby
40
47
  class Vehicle
41
- attr_accessor :seatbelt_on, :time_used, :auto_shop_busy
48
+ attr_accessor :seatbelt_on, :time_used, :auto_shop_busy, :parking_meter_number
42
49
 
43
50
  state_machine :state, initial: :parked do
44
51
  before_transition parked: any - :parked, do: :put_on_seatbelt
45
-
52
+
46
53
  after_transition on: :crash, do: :tow
47
54
  after_transition on: :repair, do: :fix
48
55
  after_transition any => :parked do |vehicle, transition|
@@ -61,6 +68,18 @@ class Vehicle
61
68
  transition [:idling, :first_gear] => :parked
62
69
  end
63
70
 
71
+ before_transition on: :park do |vehicle, transition|
72
+ # If using Rails:
73
+ # options = transition.args.extract_options!
74
+
75
+ options = transition.args.last.is_a?(Hash) ? transition.args.pop : {}
76
+ meter_number = options[:meter_number]
77
+
78
+ unless meter_number.nil?
79
+ vehicle.parking_meter_number = meter_number
80
+ end
81
+ end
82
+
64
83
  event :ignite do
65
84
  transition stalled: same, parked: :idling
66
85
  end
@@ -130,6 +149,7 @@ class Vehicle
130
149
  @seatbelt_on = false
131
150
  @time_used = 0
132
151
  @auto_shop_busy = true
152
+ @parking_meter_number = nil
133
153
  super() # NOTE: This *must* be called, otherwise states won't get initialized
134
154
  end
135
155
 
@@ -200,6 +220,11 @@ vehicle.park! # => StateMachines:InvalidTransition: Cannot tra
200
220
  vehicle.state?(:parked) # => false
201
221
  vehicle.state?(:invalid) # => IndexError: :invalid is an invalid name
202
222
 
223
+ # Transition callbacks can receive arguments
224
+ vehicle.park(meter_number: '12345') # => true
225
+ vehicle.parked? # => true
226
+ vehicle.parking_meter_number # => "12345"
227
+
203
228
  # Namespaced machines have uniquely-generated methods
204
229
  vehicle.alarm_state # => 1
205
230
  vehicle.alarm_state_name # => :active
@@ -256,30 +281,36 @@ vehicle.state_name # => :parked
256
281
 
257
282
  ## Testing
258
283
 
259
- State Machines provides a `TestHelper` module with assertion methods to make testing state machines easier and more expressive.
284
+ State Machines provides an optional `TestHelper` module with assertion methods to make testing state machines easier and more expressive.
285
+
286
+ **Note: TestHelper is not required by default** - you must explicitly require it in your test files.
260
287
 
261
288
  ### Setup
262
289
 
263
- Include the test helper in your test class:
290
+ First, require the test helper module, then include it in your test class:
264
291
 
265
292
  ```ruby
266
293
  # For Minitest
294
+ require 'state_machines/test_helper'
295
+
267
296
  class VehicleTest < Minitest::Test
268
297
  include StateMachines::TestHelper
269
-
298
+
270
299
  def test_initial_state
271
300
  vehicle = Vehicle.new
272
- assert_state vehicle, :state, :parked
301
+ assert_sm_state vehicle, :parked
273
302
  end
274
303
  end
275
304
 
276
- # For RSpec
305
+ # For RSpec
306
+ require 'state_machines/test_helper'
307
+
277
308
  RSpec.describe Vehicle do
278
309
  include StateMachines::TestHelper
279
-
310
+
280
311
  it "starts in parked state" do
281
312
  vehicle = Vehicle.new
282
- assert_state vehicle, :state, :parked
313
+ assert_sm_state vehicle, :parked
283
314
  end
284
315
  end
285
316
  ```
@@ -292,10 +323,17 @@ The TestHelper provides both basic assertions and comprehensive state machine-sp
292
323
 
293
324
  ```ruby
294
325
  vehicle = Vehicle.new
295
- assert_state vehicle, :state, :parked
296
- assert_can_transition vehicle, :ignite
297
- assert_cannot_transition vehicle, :shift_up
298
- assert_transition vehicle, :ignite, :state, :idling
326
+
327
+ # New standardized API (all methods prefixed with assert_sm_)
328
+ assert_sm_state(vehicle, :parked) # Uses default :state machine
329
+ assert_sm_state(vehicle, :parked, machine_name: :status) # Specify machine explicitly
330
+ assert_sm_can_transition(vehicle, :ignite) # Test transition capability
331
+ assert_sm_cannot_transition(vehicle, :shift_up) # Test transition restriction
332
+ assert_sm_transition(vehicle, :ignite, :idling) # Test actual transition
333
+
334
+ # Multi-FSM examples
335
+ assert_sm_state(vehicle, :inactive, machine_name: :insurance_state) # Test insurance state
336
+ assert_sm_can_transition(vehicle, :buy_insurance, machine_name: :insurance_state)
299
337
  ```
300
338
 
301
339
  #### Extended State Machine Assertions
@@ -308,7 +346,7 @@ vehicle = Vehicle.new
308
346
  assert_sm_states_list machine, [:parked, :idling, :stalled]
309
347
  assert_sm_initial_state machine, :parked
310
348
 
311
- # Event behavior
349
+ # Event behavior
312
350
  assert_sm_event_triggers vehicle, :ignite
313
351
  refute_sm_event_triggers vehicle, :shift_up
314
352
  assert_sm_event_raises_error vehicle, :invalid_event, StateMachines::InvalidTransition
@@ -317,8 +355,106 @@ assert_sm_event_raises_error vehicle, :invalid_event, StateMachines::InvalidTran
317
355
  assert_sm_state_persisted record, expected: :active
318
356
  ```
319
357
 
358
+ #### Indirect Event Testing
359
+
360
+ Test that methods trigger state machine events indirectly:
361
+
362
+ ```ruby
363
+ # Minitest style
364
+ vehicle = Vehicle.new
365
+ vehicle.ignite # Put in idling state
366
+
367
+ # Test that a custom method triggers a specific event
368
+ assert_sm_triggers_event(vehicle, :crash) do
369
+ vehicle.redline # Custom method that calls crash! internally
370
+ end
371
+
372
+ # Test multiple events
373
+ assert_sm_triggers_event(vehicle, [:crash, :emergency]) do
374
+ vehicle.emergency_stop
375
+ end
376
+
377
+ # Test on specific state machine (multi-FSM support)
378
+ assert_sm_triggers_event(vehicle, :disable, machine_name: :alarm) do
379
+ vehicle.turn_off_alarm
380
+ end
381
+ ```
382
+
383
+ ```ruby
384
+ # RSpec style (coming soon with proper matcher support)
385
+ RSpec.describe Vehicle do
386
+ include StateMachines::TestHelper
387
+
388
+ it "triggers crash when redlining" do
389
+ vehicle = Vehicle.new
390
+ vehicle.ignite
391
+
392
+ expect_to_trigger_event(vehicle, :crash) do
393
+ vehicle.redline
394
+ end
395
+ end
396
+ end
397
+ ```
398
+
399
+ #### Callback Definition Testing (TDD Support)
400
+
401
+ Verify that callbacks are properly defined in your state machine:
402
+
403
+ ```ruby
404
+ # Test after_transition callbacks
405
+ assert_after_transition(Vehicle, on: :crash, do: :tow)
406
+ assert_after_transition(Vehicle, from: :stalled, to: :parked, do: :log_repair)
407
+
408
+ # Test before_transition callbacks
409
+ assert_before_transition(Vehicle, from: :parked, do: :put_on_seatbelt)
410
+ assert_before_transition(Vehicle, on: :ignite, if: :seatbelt_on?)
411
+
412
+ # Works with machine instances too
413
+ machine = Vehicle.state_machine(:state)
414
+ assert_after_transition(machine, on: :crash, do: :tow)
415
+ ```
416
+
417
+ #### Multiple State Machine Support
418
+
419
+ The TestHelper fully supports objects with multiple state machines:
420
+
421
+ ```ruby
422
+ # Example: StarfleetShip with 3 state machines
423
+ ship = StarfleetShip.new
424
+
425
+ # Test states on different machines
426
+ assert_sm_state(ship, :docked, machine_name: :status) # Main ship status
427
+ assert_sm_state(ship, :down, machine_name: :shields) # Shield system
428
+ assert_sm_state(ship, :standby, machine_name: :weapons) # Weapons system
429
+
430
+ # Test transitions on specific machines
431
+ assert_sm_transition(ship, :undock, :impulse, machine_name: :status)
432
+ assert_sm_transition(ship, :raise_shields, :up, machine_name: :shields)
433
+ assert_sm_transition(ship, :arm_weapons, :armed, machine_name: :weapons)
434
+
435
+ # Test event triggering across multiple machines
436
+ assert_sm_triggers_event(ship, :red_alert, machine_name: :status) do
437
+ ship.engage_combat_mode # Custom method affecting multiple systems
438
+ end
439
+
440
+ assert_sm_triggers_event(ship, :raise_shields, machine_name: :shields) do
441
+ ship.engage_combat_mode
442
+ end
443
+
444
+ # Test callback definitions on specific machines
445
+ shields_machine = StarfleetShip.state_machine(:shields)
446
+ assert_before_transition(shields_machine, from: :down, to: :up, do: :power_up_shields)
447
+
448
+ # Test persistence across multiple machines
449
+ assert_sm_state_persisted(ship, "impulse", :status)
450
+ assert_sm_state_persisted(ship, "up", :shields)
451
+ assert_sm_state_persisted(ship, "armed", :weapons)
452
+ ```
453
+
320
454
  The test helper works with both Minitest and RSpec, automatically detecting your testing framework.
321
455
 
456
+ **Note:** All methods use consistent keyword arguments with `machine_name:` as the last parameter, making the API intuitive and Grep-friendly.
457
+
322
458
  ## Additional Topics
323
459
 
324
460
  ### Explicit vs. Implicit Event Transitions
@@ -679,7 +815,7 @@ For RSpec testing, use the custom RSpec matchers:
679
815
 
680
816
  ## Contributing
681
817
 
682
- 1. Fork it ( https://github.com/state-machines/state_machines/fork )
818
+ 1. Fork it ( <https://github.com/state-machines/state_machines/fork> )
683
819
  2. Create your feature branch (`git checkout -b my-new-feature`)
684
820
  3. Commit your changes (`git commit -am 'Add some feature'`)
685
821
  4. Push to the branch (`git push origin my-new-feature`)
@@ -8,7 +8,6 @@ module StateMachines
8
8
  # state of the transition match, in addition to if/unless conditionals for
9
9
  # an object's state.
10
10
  class Branch
11
-
12
11
  include EvalHelpers
13
12
 
14
13
  # The condition that must be met on an object
@@ -31,7 +30,7 @@ module StateMachines
31
30
  attr_reader :known_states
32
31
 
33
32
  # Creates a new branch
34
- def initialize(options = {}) #:nodoc:
33
+ def initialize(options = {}) # :nodoc:
35
34
  # Build conditionals
36
35
  @if_condition = options.delete(:if)
37
36
  @unless_condition = options.delete(:unless)
@@ -39,9 +38,9 @@ module StateMachines
39
38
  # Build event requirement
40
39
  @event_requirement = build_matcher(options, :on, :except_on)
41
40
 
42
- if (options.keys - [:from, :to, :on, :except_from, :except_to, :except_on]).empty?
41
+ if (options.keys - %i[from to on except_from except_to except_on]).empty?
43
42
  # Explicit from/to requirements specified
44
- @state_requirements = [{from: build_matcher(options, :from, :except_from), to: build_matcher(options, :to, :except_to)}]
43
+ @state_requirements = [{ from: build_matcher(options, :from, :except_from), to: build_matcher(options, :to, :except_to) }]
45
44
  else
46
45
  # Separate out the event requirement
47
46
  options.delete(:on)
@@ -51,7 +50,7 @@ module StateMachines
51
50
  @state_requirements = options.collect do |from, to|
52
51
  from = WhitelistMatcher.new(from) unless from.is_a?(Matcher)
53
52
  to = WhitelistMatcher.new(to) unless to.is_a?(Matcher)
54
- {from: from, to: to}
53
+ { from: from, to: to }
55
54
  end
56
55
  end
57
56
 
@@ -59,7 +58,7 @@ module StateMachines
59
58
  # on the priority in which tracked states should be added.
60
59
  @known_states = []
61
60
  @state_requirements.each do |state_requirement|
62
- [:from, :to].each { |option| @known_states |= state_requirement[option].values }
61
+ %i[from to].each { |option| @known_states |= state_requirement[option].values }
63
62
  end
64
63
  end
65
64
 
@@ -109,25 +108,27 @@ module StateMachines
109
108
  # * <tt>:guard</tt> - Whether to guard matches with the if/unless
110
109
  # conditionals defined for this branch. Default is true.
111
110
  #
111
+ # Event arguments are passed to guard conditions if they accept multiple parameters.
112
+ #
112
113
  # == Examples
113
114
  #
114
115
  # branch = StateMachines::Branch.new(:parked => :idling, :on => :ignite)
115
116
  #
116
117
  # branch.match(object, :on => :ignite) # => {:to => ..., :from => ..., :on => ...}
117
118
  # branch.match(object, :on => :park) # => nil
118
- def match(object, query = {})
119
+ def match(object, query = {}, event_args = [])
119
120
  StateMachines::OptionsValidator.assert_valid_keys!(query, :from, :to, :on, :guard)
120
121
 
121
- if (match = match_query(query)) && matches_conditions?(object, query)
122
- match
123
- end
122
+ return unless (match = match_query(query)) && matches_conditions?(object, query, event_args)
123
+
124
+ match
124
125
  end
125
126
 
126
127
  def draw(graph, event, valid_states, io = $stdout)
127
128
  machine.renderer.draw_branch(self, graph, event, valid_states, io)
128
129
  end
129
130
 
130
- protected
131
+ protected
131
132
 
132
133
  # Builds a matcher strategy to use for the given options. If neither a
133
134
  # whitelist nor a blacklist option is specified, then an AllMatcher is
@@ -168,7 +169,7 @@ module StateMachines
168
169
  # matching requirement is found, then it is returned.
169
170
  def match_states(query)
170
171
  state_requirements.detect do |state_requirement|
171
- [:from, :to].all? { |option| matches_requirement?(query, option, state_requirement[option]) }
172
+ %i[from to].all? { |option| matches_requirement?(query, option, state_requirement[option]) }
172
173
  end
173
174
  end
174
175
 
@@ -179,11 +180,23 @@ module StateMachines
179
180
  end
180
181
 
181
182
  # Verifies that the conditionals for this branch evaluate to true for the
182
- # given object
183
- def matches_conditions?(object, query)
184
- query[:guard] == false ||
185
- Array(if_condition).all? { |condition| evaluate_method(object, condition) } &&
186
- !Array(unless_condition).any? { |condition| evaluate_method(object, condition) }
183
+ # given object. Event arguments are passed to guards that accept multiple parameters.
184
+ def matches_conditions?(object, query, event_args = [])
185
+ case [query[:guard], if_condition, unless_condition]
186
+ in [false, _, _]
187
+ true
188
+ in [_, nil, nil]
189
+ true
190
+ in [_, if_conds, nil] if if_conds
191
+ Array(if_conds).all? { |condition| evaluate_method_with_event_args(object, condition, event_args) }
192
+ in [_, nil, unless_conds] if unless_conds
193
+ Array(unless_conds).none? { |condition| evaluate_method_with_event_args(object, condition, event_args) }
194
+ in [_, if_conds, unless_conds] if if_conds || unless_conds
195
+ Array(if_conds).all? { |condition| evaluate_method_with_event_args(object, condition, event_args) } &&
196
+ Array(unless_conds).none? { |condition| evaluate_method_with_event_args(object, condition, event_args) }
197
+ else
198
+ true
199
+ end
187
200
  end
188
201
  end
189
202
  end
@@ -124,7 +124,7 @@ module StateMachines
124
124
  # callback can be found in their attribute definitions.
125
125
  def initialize(type, *args, &block)
126
126
  @type = type
127
- raise ArgumentError, 'Type must be :before, :after, :around, or :failure' unless [:before, :after, :around, :failure].include?(type)
127
+ raise ArgumentError, 'Type must be :before, :after, :around, or :failure' unless %i[before after around failure].include?(type)
128
128
 
129
129
  options = args.last.is_a?(Hash) ? args.pop : {}
130
130
  @methods = args
@@ -132,7 +132,7 @@ module StateMachines
132
132
  @methods << block if block_given?
133
133
  raise ArgumentError, 'Method(s) for callback must be specified' unless @methods.any?
134
134
 
135
- options = {bind_to_object: self.class.bind_to_object, terminator: self.class.terminator}.merge(options)
135
+ options = { bind_to_object: self.class.bind_to_object, terminator: self.class.terminator }.merge(options)
136
136
 
137
137
  # Proxy lambda blocks so that they're bound to the object
138
138
  bind_to_object = options.delete(:bind_to_object)
@@ -156,16 +156,16 @@ module StateMachines
156
156
  #
157
157
  # If a terminator has been configured and it matches the result from the
158
158
  # evaluated method, then the callback chain should be halted.
159
- def call(object, context = {}, *args, &block)
159
+ def call(object, context = {}, *, &)
160
160
  if @branch.matches?(object, context)
161
- run_methods(object, context, 0, *args, &block)
161
+ run_methods(object, context, 0, *, &)
162
162
  true
163
163
  else
164
164
  false
165
165
  end
166
166
  end
167
167
 
168
- private
168
+ private
169
169
 
170
170
  # Runs all of the methods configured for this callback.
171
171
  #
@@ -179,7 +179,7 @@ module StateMachines
179
179
  def run_methods(object, context = {}, index = 0, *args, &block)
180
180
  if type == :around
181
181
  current_method = @methods[index]
182
- if current_method
182
+ if current_method
183
183
  yielded = false
184
184
  evaluate_method(object, current_method, *args) do
185
185
  yielded = true
@@ -187,13 +187,13 @@ module StateMachines
187
187
  end
188
188
 
189
189
  throw :halt unless yielded
190
- else
191
- yield if block_given?
190
+ elsif block_given?
191
+ yield
192
192
  end
193
193
  else
194
194
  @methods.each do |method|
195
195
  result = evaluate_method(object, method, *args)
196
- throw :halt if @terminator && @terminator.call(result)
196
+ throw :halt if @terminator&.call(result)
197
197
  end
198
198
  end
199
199
  end
@@ -206,13 +206,12 @@ module StateMachines
206
206
  arity += 1 if arity >= 0 # Make sure the object gets passed
207
207
  arity += 1 if arity == 1 && type == :around # Make sure the block gets passed
208
208
 
209
- method = lambda { |object, *args| object.instance_exec(*args, &block) }
210
-
209
+ method = ->(object, *args) { object.instance_exec(*args, &block) }
211
210
 
212
211
  # Proxy arity to the original block
213
212
  (
214
- class << method;
215
- self;
213
+ class << method
214
+ self
216
215
  end).class_eval do
217
216
  define_method(:arity) { arity }
218
217
  end
@@ -24,7 +24,6 @@ require 'state_machines/transition_collection'
24
24
  require 'state_machines/branch'
25
25
 
26
26
  require 'state_machines/helper_module'
27
- require 'state_machines/state'
28
27
  require 'state_machines/callback'
29
28
  require 'state_machines/node_collection'
30
29
 
@@ -6,7 +6,7 @@ module StateMachines
6
6
  # The object that failed
7
7
  attr_reader :object
8
8
 
9
- def initialize(object, message = nil) #:nodoc:
9
+ def initialize(object, message = nil) # :nodoc:
10
10
  @object = object
11
11
 
12
12
  super(message)
@@ -49,12 +49,13 @@ module StateMachines
49
49
  # The event that was attempted to be run
50
50
  attr_reader :event
51
51
 
52
- def initialize(object, event_name) #:nodoc:
52
+ def initialize(object, event_name) # :nodoc:
53
53
  @event = event_name
54
54
 
55
55
  super(object, "#{event.inspect} is an unknown state machine event")
56
56
  end
57
57
  end
58
+
58
59
  # An invalid transition was attempted
59
60
  class InvalidTransition < Error
60
61
  # The machine attempting to be transitioned
@@ -63,7 +64,7 @@ module StateMachines
63
64
  # The current state value for the machine
64
65
  attr_reader :from
65
66
 
66
- def initialize(object, machine, event) #:nodoc:
67
+ def initialize(object, machine, event) # :nodoc:
67
68
  @machine = machine
68
69
  @from_state = machine.states.match!(object)
69
70
  @from = machine.read(object, :state)
@@ -101,7 +102,7 @@ module StateMachines
101
102
  # The set of events that failed the transition(s)
102
103
  attr_reader :events
103
104
 
104
- def initialize(object, events) #:nodoc:
105
+ def initialize(object, events) # :nodoc:
105
106
  @events = events
106
107
 
107
108
  super(object, "Cannot run events in parallel: #{events * ', '}")