state_machines 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/Gemfile +0 -2
- data/README.md +25 -0
- data/Rakefile +10 -1
- data/lib/state_machines/branch.rb +0 -4
- data/lib/state_machines/core.rb +23 -5
- data/lib/state_machines/error.rb +81 -2
- data/lib/state_machines/event.rb +2 -20
- data/lib/state_machines/event_collection.rb +25 -27
- data/lib/state_machines/extensions.rb +34 -34
- data/lib/state_machines/integrations.rb +98 -90
- data/lib/state_machines/integrations/base.rb +11 -60
- data/lib/state_machines/matcher.rb +0 -2
- data/lib/state_machines/node_collection.rb +0 -2
- data/lib/state_machines/path_collection.rb +0 -2
- data/lib/state_machines/state.rb +0 -3
- data/lib/state_machines/state_collection.rb +17 -19
- data/lib/state_machines/state_context.rb +1 -6
- data/lib/state_machines/transition.rb +0 -56
- data/lib/state_machines/version.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/state_machines/assertions_spec.rb +31 -0
- data/spec/state_machines/branch_spec.rb +827 -0
- data/spec/state_machines/callbacks_spec.rb +706 -0
- data/spec/state_machines/errors_spec.rb +1 -0
- data/spec/state_machines/event_collection_spec.rb +401 -0
- data/spec/state_machines/event_spec.rb +1140 -0
- data/spec/{helpers → state_machines}/helper_spec.rb +0 -0
- data/spec/state_machines/integration_base_spec.rb +12 -0
- data/spec/state_machines/integration_spec.rb +132 -0
- data/spec/state_machines/invalid_event_spec.rb +19 -0
- data/spec/state_machines/invalid_parallel_transition_spec.rb +18 -0
- data/spec/state_machines/invalid_transition_spec.rb +114 -0
- data/spec/state_machines/machine_collection_spec.rb +606 -0
- data/spec/{machine_spec.rb → state_machines/machine_spec.rb} +11 -2
- data/spec/{matcher_helpers_spec.rb → state_machines/matcher_helpers_spec.rb} +0 -0
- data/spec/{matcher_spec.rb → state_machines/matcher_spec.rb} +0 -0
- data/spec/{node_collection_spec.rb → state_machines/node_collection_spec.rb} +0 -0
- data/spec/{path_collection_spec.rb → state_machines/path_collection_spec.rb} +0 -0
- data/spec/{path_spec.rb → state_machines/path_spec.rb} +0 -0
- data/spec/{state_collection_spec.rb → state_machines/state_collection_spec.rb} +0 -0
- data/spec/{state_context_spec.rb → state_machines/state_context_spec.rb} +0 -0
- data/spec/{state_machine_spec.rb → state_machines/state_machine_spec.rb} +0 -0
- data/spec/{state_spec.rb → state_machines/state_spec.rb} +0 -0
- data/spec/{transition_collection_spec.rb → state_machines/transition_collection_spec.rb} +0 -0
- data/spec/{transition_spec.rb → state_machines/transition_spec.rb} +0 -0
- data/spec/support/migration_helpers.rb +9 -0
- data/state_machines.gemspec +3 -1
- metadata +68 -45
- data/lib/state_machines/yard.rb +0 -8
- data/spec/errors/default_spec.rb +0 -14
- data/spec/errors/with_message_spec.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eee931d0f563b659a9e786dc0eea93ed9f9f537
|
4
|
+
data.tar.gz: f53da4d08eecd750e4b416f5926e31b49be341f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1fde9ad6a6b0fb3a3f066a87f7f80c90d78c9f7d633f92f67ff0f3104bc01d16bddf4485f1b24ab3dc35bd14e6e348b8bc3ee8f45cce9edc89ef771869b9229
|
7
|
+
data.tar.gz: 9f07e5b0c0d579557d0a4648b909922a85f45653366ed37e738a3176d52e4ef5ed586471395ea1ca1fcf22109a2d3dda0139e7676f9199666348c108904cabdc
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://travis-ci.org/seuros/state_machines)
|
2
|
+
[](https://codeclimate.com/github/seuros/state_machines)
|
1
3
|
# State Machines
|
2
4
|
|
3
5
|
State Machines adds support for creating state machines for attributes on any Ruby class.
|
@@ -20,6 +22,29 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
TODO: Write usage instructions here
|
22
24
|
|
25
|
+
## Dependencies
|
26
|
+
|
27
|
+
Ruby versions officially supported and tested:
|
28
|
+
|
29
|
+
* Ruby (MRI) 1.9.3+
|
30
|
+
* JRuby (1.9)
|
31
|
+
* Rubinius
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
For graphing state machine:
|
36
|
+
|
37
|
+
* [state_machines-graphviz](http://github.com/seuros/state_machines-graphviz)
|
38
|
+
|
39
|
+
For documenting state machines:
|
40
|
+
|
41
|
+
* [state_machines-yard](http://github.com/seuros/state_machines-yard)
|
42
|
+
|
43
|
+
|
44
|
+
## TODO
|
45
|
+
|
46
|
+
Add matchers/assertions for rspec and minitest
|
47
|
+
|
23
48
|
## Contributing
|
24
49
|
|
25
50
|
1. Fork it ( https://github.com/seuros/state_machines/fork )
|
data/Rakefile
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
require 'state_machines/matcher'
|
2
|
-
require 'state_machines/eval_helpers'
|
3
|
-
require 'state_machines/assertions'
|
4
|
-
|
5
1
|
module StateMachines
|
6
2
|
# Represents a set of requirements that must be met in order for a transition
|
7
3
|
# or callback to occur. Branches verify that the event, from state, and to
|
data/lib/state_machines/core.rb
CHANGED
@@ -3,23 +3,41 @@
|
|
3
3
|
# * StateMachines::MacroMethods which adds the state_machine DSL to your class
|
4
4
|
# * A set of initializers for setting state_machine defaults based on the current
|
5
5
|
# running environment (such as within Rails)
|
6
|
-
require 'state_machines/error'
|
7
6
|
require 'state_machines/assertions'
|
7
|
+
require 'state_machines/error'
|
8
8
|
|
9
|
-
require 'state_machines/machine_collection'
|
10
9
|
require 'state_machines/extensions'
|
11
10
|
|
12
|
-
require 'state_machines/integrations/base'
|
13
11
|
require 'state_machines/integrations'
|
12
|
+
require 'state_machines/integrations/base'
|
13
|
+
|
14
|
+
require 'state_machines/eval_helpers'
|
15
|
+
|
16
|
+
require 'singleton'
|
17
|
+
require 'state_machines/matcher'
|
18
|
+
require 'state_machines/matcher_helpers'
|
19
|
+
|
20
|
+
require 'state_machines/transition'
|
21
|
+
require 'state_machines/transition_collection'
|
22
|
+
|
23
|
+
require 'state_machines/branch'
|
14
24
|
|
15
25
|
require 'state_machines/helper_module'
|
16
26
|
require 'state_machines/state'
|
17
|
-
require 'state_machines/event'
|
18
27
|
require 'state_machines/callback'
|
19
28
|
require 'state_machines/node_collection'
|
29
|
+
|
30
|
+
require 'state_machines/state_context'
|
31
|
+
require 'state_machines/state'
|
20
32
|
require 'state_machines/state_collection'
|
33
|
+
|
34
|
+
require 'state_machines/event'
|
21
35
|
require 'state_machines/event_collection'
|
36
|
+
|
37
|
+
require 'state_machines/path'
|
22
38
|
require 'state_machines/path_collection'
|
23
|
-
|
39
|
+
|
24
40
|
require 'state_machines/machine'
|
41
|
+
require 'state_machines/machine_collection'
|
42
|
+
|
25
43
|
require 'state_machines/macro_methods'
|
data/lib/state_machines/error.rb
CHANGED
@@ -3,11 +3,90 @@ module StateMachines
|
|
3
3
|
class Error < StandardError
|
4
4
|
# The object that failed
|
5
5
|
attr_reader :object
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(object, message = nil) #:nodoc:
|
8
8
|
@object = object
|
9
|
-
|
9
|
+
|
10
10
|
super(message)
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
# An invalid integration was specified
|
15
|
+
class IntegrationNotFound < Error
|
16
|
+
def initialize(name)
|
17
|
+
super(nil, "#{name.inspect} is an invalid integration")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# An invalid integration was registered
|
22
|
+
class IntegrationError < StandardError
|
23
|
+
end
|
24
|
+
|
25
|
+
# An invalid event was specified
|
26
|
+
class InvalidEvent < Error
|
27
|
+
# The event that was attempted to be run
|
28
|
+
attr_reader :event
|
29
|
+
|
30
|
+
def initialize(object, event_name) #:nodoc:
|
31
|
+
@event = event_name
|
32
|
+
|
33
|
+
super(object, "#{event.inspect} is an unknown state machine event")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# An invalid transition was attempted
|
37
|
+
class InvalidTransition < Error
|
38
|
+
# The machine attempting to be transitioned
|
39
|
+
attr_reader :machine
|
40
|
+
|
41
|
+
# The current state value for the machine
|
42
|
+
attr_reader :from
|
43
|
+
|
44
|
+
def initialize(object, machine, event) #:nodoc:
|
45
|
+
@machine = machine
|
46
|
+
@from_state = machine.states.match!(object)
|
47
|
+
@from = machine.read(object, :state)
|
48
|
+
@event = machine.events.fetch(event)
|
49
|
+
errors = machine.errors_for(object)
|
50
|
+
|
51
|
+
message = "Cannot transition #{machine.name} via :#{self.event} from #{from_name.inspect}"
|
52
|
+
message << " (Reason(s): #{errors})" unless errors.empty?
|
53
|
+
super(object, message)
|
54
|
+
end
|
55
|
+
|
56
|
+
# The event that triggered the failed transition
|
57
|
+
def event
|
58
|
+
@event.name
|
59
|
+
end
|
60
|
+
|
61
|
+
# The fully-qualified name of the event that triggered the failed transition
|
62
|
+
def qualified_event
|
63
|
+
@event.qualified_name
|
64
|
+
end
|
65
|
+
|
66
|
+
# The name for the current state
|
67
|
+
def from_name
|
68
|
+
@from_state.name
|
69
|
+
end
|
70
|
+
|
71
|
+
# The fully-qualified name for the current state
|
72
|
+
def qualified_from_name
|
73
|
+
@from_state.qualified_name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# A set of transition failed to run in parallel
|
78
|
+
class InvalidParallelTransition < Error
|
79
|
+
# The set of events that failed the transition(s)
|
80
|
+
attr_reader :events
|
81
|
+
|
82
|
+
def initialize(object, events) #:nodoc:
|
83
|
+
@events = events
|
84
|
+
|
85
|
+
super(object, "Cannot run events in parallel: #{events * ', '}")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# A method was called in an invalid state context
|
90
|
+
class InvalidContext < Error
|
91
|
+
end
|
13
92
|
end
|
data/lib/state_machines/event.rb
CHANGED
@@ -1,22 +1,4 @@
|
|
1
|
-
require 'state_machines/transition'
|
2
|
-
require 'state_machines/branch'
|
3
|
-
require 'state_machines/assertions'
|
4
|
-
require 'state_machines/matcher_helpers'
|
5
|
-
require 'state_machines/error'
|
6
|
-
|
7
1
|
module StateMachines
|
8
|
-
# An invalid event was specified
|
9
|
-
class InvalidEvent < Error
|
10
|
-
# The event that was attempted to be run
|
11
|
-
attr_reader :event
|
12
|
-
|
13
|
-
def initialize(object, event_name) #:nodoc:
|
14
|
-
@event = event_name
|
15
|
-
|
16
|
-
super(object, "#{event.inspect} is an unknown state machine event")
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
2
|
# An event defines an action that transitions an attribute from one state to
|
21
3
|
# another. The state that an attribute is transitioned to depends on the
|
22
4
|
# branches configured for the event.
|
@@ -58,8 +40,8 @@ module StateMachines
|
|
58
40
|
reset
|
59
41
|
|
60
42
|
# Output a warning if another event has a conflicting qualified name
|
61
|
-
if conflict = machine.owner_class.state_machines.detect { |
|
62
|
-
|
43
|
+
if conflict = machine.owner_class.state_machines.detect { |_other_name, other_machine| other_machine != @machine && other_machine.events[qualified_name, :qualified_name] }
|
44
|
+
_name, other_machine = conflict
|
63
45
|
warn "Event #{qualified_name.inspect} for #{machine.name.inspect} is already defined in #{other_machine.name.inspect}"
|
64
46
|
else
|
65
47
|
add_actions
|
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'state_machines/node_collection'
|
2
|
-
|
3
1
|
module StateMachines
|
4
2
|
# Represents a collection of events in a state machine
|
5
3
|
class EventCollection < NodeCollection
|
6
4
|
def initialize(machine) #:nodoc:
|
7
5
|
super(machine, :index => [:name, :qualified_name])
|
8
6
|
end
|
9
|
-
|
7
|
+
|
10
8
|
# Gets the list of events that can be fired on the given object.
|
11
9
|
#
|
12
10
|
# Valid requirement options:
|
@@ -41,9 +39,9 @@ module StateMachines
|
|
41
39
|
# vehicle.state = 'idling'
|
42
40
|
# events.valid_for(vehicle) # => [#<StateMachines::Event name=:park transitions=[:idling => :parked]>]
|
43
41
|
def valid_for(object, requirements = {})
|
44
|
-
match(requirements).select {|event| event.can_fire?(object, requirements)}
|
42
|
+
match(requirements).select { |event| event.can_fire?(object, requirements) }
|
45
43
|
end
|
46
|
-
|
44
|
+
|
47
45
|
# Gets the list of transitions that can be run on the given object.
|
48
46
|
#
|
49
47
|
# Valid requirement options:
|
@@ -81,9 +79,9 @@ module StateMachines
|
|
81
79
|
# # Search for explicit transitions regardless of the current state
|
82
80
|
# events.transitions_for(vehicle, :from => :parked) # => [#<StateMachines::Transition attribute=:state event=:ignite from="parked" from_name=:parked to="idling" to_name=:idling>]
|
83
81
|
def transitions_for(object, requirements = {})
|
84
|
-
match(requirements).map {|event| event.transition_for(object, requirements)}.compact
|
82
|
+
match(requirements).map { |event| event.transition_for(object, requirements) }.compact
|
85
83
|
end
|
86
|
-
|
84
|
+
|
87
85
|
# Gets the transition that should be performed for the event stored in the
|
88
86
|
# given object's event attribute. This also takes an additional parameter
|
89
87
|
# for automatically invalidating the object if the event or transition are
|
@@ -115,27 +113,27 @@ module StateMachines
|
|
115
113
|
# events.attribute_transition_for(vehicle) # => #<StateMachines::Transition attribute=:state event=:ignite from="parked" from_name=:parked to="idling" to_name=:idling>
|
116
114
|
def attribute_transition_for(object, invalidate = false)
|
117
115
|
return unless machine.action
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
116
|
+
|
117
|
+
# TODO, simplify
|
118
|
+
machine.read(object, :event_transition) || if event_name = machine.read(object, :event)
|
119
|
+
if event = self[event_name.to_sym, :name]
|
120
|
+
event.transition_for(object) || begin
|
121
|
+
# No valid transition: invalidate
|
122
|
+
machine.invalidate(object, :event, :invalid_event, [[:state, machine.states.match!(object).human_name(object.class)]]) if invalidate
|
123
|
+
false
|
124
|
+
end
|
125
|
+
else
|
126
|
+
# Event is unknown: invalidate
|
127
|
+
machine.invalidate(object, :event, :invalid) if invalidate
|
128
|
+
false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
134
132
|
end
|
135
|
-
|
133
|
+
|
136
134
|
private
|
137
|
-
|
138
|
-
|
139
|
-
|
135
|
+
def match(requirements) #:nodoc:
|
136
|
+
requirements && requirements[:on] ? [fetch(requirements.delete(:on))] : self
|
137
|
+
end
|
140
138
|
end
|
141
139
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module StateMachines
|
3
2
|
module ClassMethods
|
4
3
|
def self.extended(base) #:nodoc:
|
@@ -6,20 +5,20 @@ module StateMachines
|
|
6
5
|
@state_machines = MachineCollection.new
|
7
6
|
end
|
8
7
|
end
|
9
|
-
|
8
|
+
|
10
9
|
# Gets the current list of state machines defined for this class. This
|
11
10
|
# class-level attribute acts like an inheritable attribute. The attribute
|
12
11
|
# is available to each subclass, each having a copy of its superclass's
|
13
12
|
# attribute.
|
14
|
-
#
|
13
|
+
#
|
15
14
|
# The hash of state machines maps <tt>:attribute</tt> => +machine+, e.g.
|
16
|
-
#
|
15
|
+
#
|
17
16
|
# Vehicle.state_machines # => {:state => #<StateMachines::Machine:0xb6f6e4a4 ...>}
|
18
17
|
def state_machines
|
19
18
|
@state_machines ||= superclass.state_machines.dup
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
21
|
+
|
23
22
|
module InstanceMethods
|
24
23
|
# Runs one or more events in parallel. All events will run through the
|
25
24
|
# following steps:
|
@@ -27,7 +26,7 @@ module StateMachines
|
|
27
26
|
# * Persist state
|
28
27
|
# * Invoke action
|
29
28
|
# * After callbacks
|
30
|
-
#
|
29
|
+
#
|
31
30
|
# For example, if two events (for state machines A and B) are run in
|
32
31
|
# parallel, the order in which steps are run is:
|
33
32
|
# * A - Before transition callbacks
|
@@ -38,62 +37,62 @@ module StateMachines
|
|
38
37
|
# * B - Invoke action (only if different than A's action)
|
39
38
|
# * A - After transition callbacks
|
40
39
|
# * B - After transition callbacks
|
41
|
-
#
|
40
|
+
#
|
42
41
|
# *Note* that multiple events on the same state machine / attribute cannot
|
43
42
|
# be run in parallel. If this is attempted, an ArgumentError will be
|
44
43
|
# raised.
|
45
|
-
#
|
44
|
+
#
|
46
45
|
# == Halting callbacks
|
47
|
-
#
|
46
|
+
#
|
48
47
|
# When running multiple events in parallel, special consideration should
|
49
48
|
# be taken with regard to how halting within callbacks affects the flow.
|
50
|
-
#
|
49
|
+
#
|
51
50
|
# For *before* callbacks, any <tt>:halt</tt> error that's thrown will
|
52
51
|
# immediately cancel the perform for all transitions. As a result, it's
|
53
52
|
# possible for one event's transition to affect the continuation of
|
54
53
|
# another.
|
55
|
-
#
|
54
|
+
#
|
56
55
|
# On the other hand, any <tt>:halt</tt> error that's thrown within an
|
57
56
|
# *after* callback with only affect that event's transition. Other
|
58
57
|
# transitions will continue to run their own callbacks.
|
59
|
-
#
|
58
|
+
#
|
60
59
|
# == Example
|
61
|
-
#
|
60
|
+
#
|
62
61
|
# class Vehicle
|
63
62
|
# state_machine :initial => :parked do
|
64
63
|
# event :ignite do
|
65
64
|
# transition :parked => :idling
|
66
65
|
# end
|
67
|
-
#
|
66
|
+
#
|
68
67
|
# event :park do
|
69
68
|
# transition :idling => :parked
|
70
69
|
# end
|
71
70
|
# end
|
72
|
-
#
|
71
|
+
#
|
73
72
|
# state_machine :alarm_state, :namespace => 'alarm', :initial => :on do
|
74
73
|
# event :enable do
|
75
74
|
# transition all => :active
|
76
75
|
# end
|
77
|
-
#
|
76
|
+
#
|
78
77
|
# event :disable do
|
79
78
|
# transition all => :off
|
80
79
|
# end
|
81
80
|
# end
|
82
81
|
# end
|
83
|
-
#
|
82
|
+
#
|
84
83
|
# vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active">
|
85
84
|
# vehicle.state # => "parked"
|
86
85
|
# vehicle.alarm_state # => "active"
|
87
|
-
#
|
86
|
+
#
|
88
87
|
# vehicle.fire_events(:ignite, :disable_alarm) # => true
|
89
88
|
# vehicle.state # => "idling"
|
90
89
|
# vehicle.alarm_state # => "off"
|
91
|
-
#
|
90
|
+
#
|
92
91
|
# # If any event fails, the entire event chain fails
|
93
92
|
# vehicle.fire_events(:ignite, :enable_alarm) # => false
|
94
93
|
# vehicle.state # => "idling"
|
95
94
|
# vehicle.alarm_state # => "off"
|
96
|
-
#
|
95
|
+
#
|
97
96
|
# # Exception raised on invalid event
|
98
97
|
# vehicle.fire_events(:park, :invalid) # => StateMachines::InvalidEvent: :invalid is an unknown event
|
99
98
|
# vehicle.state # => "idling"
|
@@ -101,48 +100,49 @@ module StateMachines
|
|
101
100
|
def fire_events(*events)
|
102
101
|
self.class.state_machines.fire_events(self, *events)
|
103
102
|
end
|
104
|
-
|
103
|
+
|
105
104
|
# Run one or more events in parallel. If any event fails to run, then
|
106
105
|
# a StateMachines::InvalidTransition exception will be raised.
|
107
|
-
#
|
106
|
+
#
|
108
107
|
# See StateMachines::InstanceMethods#fire_events for more information.
|
109
|
-
#
|
108
|
+
#
|
110
109
|
# == Example
|
111
|
-
#
|
110
|
+
#
|
112
111
|
# class Vehicle
|
113
112
|
# state_machine :initial => :parked do
|
114
113
|
# event :ignite do
|
115
114
|
# transition :parked => :idling
|
116
115
|
# end
|
117
|
-
#
|
116
|
+
#
|
118
117
|
# event :park do
|
119
118
|
# transition :idling => :parked
|
120
119
|
# end
|
121
120
|
# end
|
122
|
-
#
|
121
|
+
#
|
123
122
|
# state_machine :alarm_state, :namespace => 'alarm', :initial => :active do
|
124
123
|
# event :enable do
|
125
124
|
# transition all => :active
|
126
125
|
# end
|
127
|
-
#
|
126
|
+
#
|
128
127
|
# event :disable do
|
129
128
|
# transition all => :off
|
130
129
|
# end
|
131
130
|
# end
|
132
131
|
# end
|
133
|
-
#
|
132
|
+
#
|
134
133
|
# vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active">
|
135
134
|
# vehicle.fire_events(:ignite, :disable_alarm) # => true
|
136
|
-
#
|
135
|
+
#
|
137
136
|
# vehicle.fire_events!(:ignite, :disable_alarm) # => StateMachines::InvalidTranstion: Cannot run events in parallel: ignite, disable_alarm
|
138
137
|
def fire_events!(*events)
|
139
138
|
run_action = [true, false].include?(events.last) ? events.pop : true
|
140
|
-
fire_events(*(events + [run_action])) ||
|
139
|
+
fire_events(*(events + [run_action])) || fail(StateMachines::InvalidParallelTransition.new(self, events))
|
141
140
|
end
|
142
|
-
|
141
|
+
|
143
142
|
protected
|
144
|
-
|
145
|
-
|
146
|
-
|
143
|
+
|
144
|
+
def initialize_state_machines(options = {}, &block) #:nodoc:
|
145
|
+
self.class.state_machines.initialize_states(self, options, &block)
|
146
|
+
end
|
147
147
|
end
|
148
148
|
end
|