aasm 4.2.0 → 4.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -1
- data/Gemfile +2 -2
- data/PLANNED_CHANGES.md +24 -4
- data/README.md +75 -5
- data/lib/aasm/aasm.rb +50 -36
- data/lib/aasm/base.rb +36 -18
- data/lib/aasm/core/event.rb +6 -5
- data/lib/aasm/core/state.rb +3 -2
- data/lib/aasm/core/transition.rb +5 -4
- data/lib/aasm/errors.rb +7 -4
- data/lib/aasm/instance_base.rb +14 -13
- data/lib/aasm/localizer.rb +1 -1
- data/lib/aasm/persistence/active_record_persistence.rb +41 -66
- data/lib/aasm/persistence/base.rb +7 -7
- data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
- data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
- data/lib/aasm/persistence/plain_persistence.rb +8 -7
- data/lib/aasm/persistence/sequel_persistence.rb +12 -10
- data/lib/aasm/state_machine.rb +11 -6
- data/lib/aasm/version.rb +1 -1
- data/spec/database.rb +27 -1
- data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
- data/spec/models/active_record/complex_active_record_example.rb +33 -0
- data/spec/models/active_record/derivate_new_dsl.rb +4 -0
- data/spec/models/active_record/false_state.rb +18 -0
- data/spec/models/active_record/gate.rb +20 -0
- data/spec/models/active_record/no_direct_assignment.rb +11 -0
- data/spec/models/active_record/no_scope.rb +11 -0
- data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
- data/spec/models/active_record/simple_new_dsl.rb +9 -0
- data/spec/models/active_record/thief.rb +15 -0
- data/spec/models/active_record/with_enum.rb +20 -0
- data/spec/models/active_record/with_false_enum.rb +16 -0
- data/spec/models/active_record/with_true_enum.rb +20 -0
- data/spec/models/basic_two_state_machines_example.rb +25 -0
- data/spec/models/callbacks/basic_multiple.rb +75 -0
- data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
- data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
- data/spec/models/callbacks/private_method_multiple.rb +44 -0
- data/spec/models/callbacks/with_args_multiple.rb +61 -0
- data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
- data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
- data/spec/models/complex_example.rb +134 -0
- data/spec/models/conversation.rb +47 -1
- data/spec/models/foo.rb +57 -0
- data/spec/models/foo_callback_multiple.rb +45 -0
- data/spec/models/guardian_multiple.rb +48 -0
- data/spec/models/initial_state_proc.rb +16 -0
- data/spec/models/invalid_persistor.rb +15 -0
- data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
- data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
- data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
- data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
- data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
- data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
- data/spec/models/mongoid/simple_mongoid.rb +12 -0
- data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
- data/spec/models/no_initial_state.rb +13 -0
- data/spec/models/parametrised_event.rb +1 -1
- data/spec/models/parametrised_event_multiple.rb +29 -0
- data/spec/models/provided_state.rb +3 -3
- data/spec/models/sequel/complex_sequel_example.rb +45 -0
- data/spec/models/sequel/sequel_multiple.rb +25 -0
- data/spec/models/sequel/sequel_simple.rb +25 -0
- data/spec/models/simple_multiple_example.rb +30 -0
- data/spec/models/sub_class.rb +4 -0
- data/spec/models/sub_class_with_more_states.rb +11 -0
- data/spec/models/super_class.rb +28 -0
- data/spec/models/transactor.rb +27 -0
- data/spec/models/valid_state_name.rb +12 -0
- data/spec/models/validator.rb +39 -0
- data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
- data/spec/unit/callback_multiple_spec.rb +295 -0
- data/spec/unit/callbacks_spec.rb +1 -1
- data/spec/unit/complex_multiple_example_spec.rb +99 -0
- data/spec/unit/edge_cases_spec.rb +16 -0
- data/spec/unit/event_multiple_spec.rb +73 -0
- data/spec/unit/event_spec.rb +11 -6
- data/spec/unit/guard_multiple_spec.rb +60 -0
- data/spec/unit/initial_state_multiple_spec.rb +15 -0
- data/spec/unit/inspection_multiple_spec.rb +201 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
- data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
- data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
- data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
- data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
- data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
- data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
- data/spec/unit/reloading_spec.rb +1 -1
- data/spec/unit/simple_multiple_example_spec.rb +63 -0
- data/spec/unit/state_spec.rb +3 -1
- data/spec/unit/subclassing_multiple_spec.rb +39 -0
- data/spec/unit/transition_spec.rb +31 -22
- metadata +73 -9
- data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -146
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b51607dcaee12f000a23ee83033925bf03dcee7
|
4
|
+
data.tar.gz: c367dd718de8264432f332ff626fc8aff05581e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a3750ab5b7758679ed9ca66fc35f04cf69347a09bc03070fd514ccbd3c111f129f907e6c4e387cf253441daf7e8e79a1045ea64da43296803434711c56a2b84
|
7
|
+
data.tar.gz: d82ff5d11b0ebae4112277283706e3bd9774517e6f4a7bece806360deda054c811ccebccfefd59c05244dd05e5351f21672932ba8071a8c2626077ba76bc585d
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
## 4.3.0
|
3
|
+
## 4.3.0
|
4
|
+
|
5
|
+
* add support for multiple state machines per class (see [issue #158](https://github.com/aasm/aasm/issues/158) and [issue #240](https://github.com/aasm/aasm/issues/240) for details)
|
6
|
+
* special thanks to [@evadne](https://github.com/evadne) for testing this feature, and providing comments and patches (see [issue #245](https://github.com/aasm/aasm/issues/245) for details)
|
4
7
|
|
5
8
|
## 4.2.0
|
6
9
|
|
data/Gemfile
CHANGED
@@ -9,7 +9,7 @@ gem 'mongoid', '~>4.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.
|
|
9
9
|
gem 'sequel'
|
10
10
|
# Since mongoid V4 requires incompatible bson V2, cannot have mongoid (V4 or greater)
|
11
11
|
# and mongo_mapper ( or mongo ) in the same application
|
12
|
-
#gem 'mongo_mapper', '~> 0.13'
|
13
|
-
#gem 'bson_ext', :platforms => :ruby
|
12
|
+
# gem 'mongo_mapper', '~> 0.13'
|
13
|
+
# gem 'bson_ext', :platforms => :ruby
|
14
14
|
|
15
15
|
gemspec
|
data/PLANNED_CHANGES.md
CHANGED
@@ -1,7 +1,27 @@
|
|
1
|
-
# Planned changes
|
1
|
+
# Planned changes
|
2
2
|
|
3
|
-
|
3
|
+
## later
|
4
4
|
|
5
|
-
|
5
|
+
* drop support for aasm_column ?
|
6
6
|
|
7
|
-
|
7
|
+
# Currently working on
|
8
|
+
|
9
|
+
|
10
|
+
# Changes so far
|
11
|
+
|
12
|
+
## version 4.3
|
13
|
+
|
14
|
+
* add support for multiple state machines per class
|
15
|
+
* class- and instance-level `aasm` methods accept a state machine selector
|
16
|
+
(aka the state machine _name_)
|
17
|
+
* if no selector/name is provided, `:default` will be used
|
18
|
+
* duplicate definitions of states and events will issue warnings
|
19
|
+
* check all tests
|
20
|
+
* _ActiveRecord_
|
21
|
+
* _Mongoid_
|
22
|
+
* _MongoMapper_
|
23
|
+
* _Sequel_
|
24
|
+
* what happen's if someone accesses `aasm`, but has defined a
|
25
|
+
state machine for `aasm(:my_name)`?
|
26
|
+
* documentation
|
27
|
+
* drop support for find_in_state, count_in_state, calculate_in_state, with_state_scope
|
data/README.md
CHANGED
@@ -99,11 +99,11 @@ class Job
|
|
99
99
|
state :running
|
100
100
|
|
101
101
|
event :run, :after => :notify_somebody do
|
102
|
-
|
103
|
-
|
104
|
-
log('Preparing to run')
|
105
|
-
end
|
102
|
+
before do
|
103
|
+
log('Preparing to run')
|
106
104
|
end
|
105
|
+
|
106
|
+
transitions :from => :sleeping, :to => :running, :after => Proc.new {|*args| set_process(*args) }
|
107
107
|
end
|
108
108
|
|
109
109
|
event :sleep do
|
@@ -312,9 +312,79 @@ job.stage1_completed
|
|
312
312
|
job.aasm.current_state # stage3
|
313
313
|
```
|
314
314
|
|
315
|
+
|
316
|
+
### Multiple state machine per class
|
317
|
+
|
318
|
+
Multiple state machines per class are supported. Be aware though, that _AASM_ has been
|
319
|
+
built with one state machine per class in mind. Nonetheless, here's how to do it:
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
class SimpleMultipleExample
|
323
|
+
include AASM
|
324
|
+
aasm(:move) do
|
325
|
+
state :standing, :initial => true
|
326
|
+
state :walking
|
327
|
+
state :running
|
328
|
+
|
329
|
+
event :walk do
|
330
|
+
transitions :from => :standing, :to => :walking
|
331
|
+
end
|
332
|
+
event :run do
|
333
|
+
transitions :from => [:standing, :walking], :to => :running
|
334
|
+
end
|
335
|
+
event :hold do
|
336
|
+
transitions :from => [:walking, :running], :to => :standing
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
aasm(:work) do
|
341
|
+
state :sleeping, :initial => true
|
342
|
+
state :processing
|
343
|
+
|
344
|
+
event :start do
|
345
|
+
transitions :from => :sleeping, :to => :processing
|
346
|
+
end
|
347
|
+
event :stop do
|
348
|
+
transitions :from => :processing, :to => :sleeping
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
simple = SimpleMultipleExample.new
|
354
|
+
|
355
|
+
simple.aasm(:move).current_state
|
356
|
+
# => :standing
|
357
|
+
simple.aasm(:work).current
|
358
|
+
# => :sleeping
|
359
|
+
|
360
|
+
simple.start
|
361
|
+
simple.aasm(:move).current_state
|
362
|
+
# => :standing
|
363
|
+
simple.aasm(:work).current
|
364
|
+
# => :processing
|
365
|
+
|
366
|
+
```
|
367
|
+
|
368
|
+
_AASM_ doesn't prohibit to define the same event in both state machines. The
|
369
|
+
latest definition "wins" and overrides previous definitions. A warning is issued:
|
370
|
+
`SimpleMultipleExample: The event name run is already used!`.
|
371
|
+
|
372
|
+
All _AASM_ class- and instance-level `aasm` methods accept a state machine selector.
|
373
|
+
So, for example, to use inspection on a class level, you have to use
|
374
|
+
|
375
|
+
```ruby
|
376
|
+
SimpleMultipleExample.aasm(:work).states
|
377
|
+
# => [:standing, :walking, :running]
|
378
|
+
```
|
379
|
+
|
380
|
+
*Final note*: Support for multiple state machines per class is a pretty new feature
|
381
|
+
(since version `4.3`), so please bear with us in case it doesn't as expected.
|
382
|
+
|
383
|
+
|
384
|
+
|
315
385
|
### ActiveRecord
|
316
386
|
|
317
|
-
AASM comes with support for ActiveRecord and allows
|
387
|
+
AASM comes with support for ActiveRecord and allows automatic persisting of the object's
|
318
388
|
state in the database.
|
319
389
|
|
320
390
|
```ruby
|
data/lib/aasm/aasm.rb
CHANGED
@@ -8,36 +8,50 @@ module AASM
|
|
8
8
|
|
9
9
|
# do not overwrite existing state machines, which could have been created by
|
10
10
|
# inheritance, see class method inherited
|
11
|
-
AASM::StateMachine[base] ||=
|
11
|
+
AASM::StateMachine[base] ||= {}
|
12
12
|
|
13
13
|
AASM::Persistence.load_persistence(base)
|
14
14
|
super
|
15
15
|
end
|
16
16
|
|
17
17
|
module ClassMethods
|
18
|
-
|
19
18
|
# make sure inheritance (aka subclassing) works with AASM
|
20
19
|
def inherited(base)
|
21
|
-
AASM::StateMachine[base] =
|
20
|
+
AASM::StateMachine[base] = {}
|
21
|
+
AASM::StateMachine[self].keys.each do |state_machine_name|
|
22
|
+
AASM::StateMachine[base][state_machine_name] = AASM::StateMachine[self][state_machine_name].clone
|
23
|
+
end
|
22
24
|
super
|
23
25
|
end
|
24
26
|
|
25
27
|
# this is the entry point for all state and event definitions
|
26
|
-
def aasm(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def aasm(*args, &block)
|
29
|
+
if args[0].is_a?(Symbol) || args[0].is_a?(String)
|
30
|
+
# using custom name
|
31
|
+
state_machine_name = args[0].to_sym
|
32
|
+
options = args[1] || {}
|
33
|
+
else
|
34
|
+
# using the default state_machine_name
|
35
|
+
state_machine_name = :default
|
36
|
+
options = args[0] || {}
|
37
|
+
end
|
38
|
+
|
39
|
+
AASM::StateMachine[self][state_machine_name] ||= AASM::StateMachine.new(state_machine_name)
|
31
40
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
aasm
|
41
|
+
@aasm ||= {}
|
42
|
+
@aasm[state_machine_name] ||= AASM::Base.new(self, state_machine_name, AASM::StateMachine[self][state_machine_name], options)
|
43
|
+
@aasm[state_machine_name].instance_eval(&block) if block # new DSL
|
44
|
+
@aasm[state_machine_name]
|
36
45
|
end
|
37
46
|
end # ClassMethods
|
38
47
|
|
39
|
-
|
40
|
-
|
48
|
+
# this is the entry point for all instance-level access to AASM
|
49
|
+
def aasm(name=:default)
|
50
|
+
unless AASM::StateMachine[self.class][name.to_sym]
|
51
|
+
raise AASM::UnknownStateMachineError.new("There is no state machine with the name '#{name}' defined in #{self.class.name}!")
|
52
|
+
end
|
53
|
+
@aasm ||= {}
|
54
|
+
@aasm[name.to_sym] ||= AASM::InstanceBase.new(self, name.to_sym)
|
41
55
|
end
|
42
56
|
|
43
57
|
private
|
@@ -56,72 +70,72 @@ private
|
|
56
70
|
return args
|
57
71
|
end
|
58
72
|
|
59
|
-
def aasm_fire_event(event_name, options, *args, &block)
|
60
|
-
event = self.class.aasm.state_machine.events[event_name]
|
73
|
+
def aasm_fire_event(state_machine_name, event_name, options, *args, &block)
|
74
|
+
event = self.class.aasm(state_machine_name).state_machine.events[event_name]
|
61
75
|
begin
|
62
|
-
old_state = aasm.state_object_for_name(aasm.current_state)
|
76
|
+
old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
|
63
77
|
|
64
78
|
# new event before callback
|
65
79
|
event.fire_callbacks(
|
66
80
|
:before,
|
67
81
|
self,
|
68
|
-
*process_args(event, aasm.current_state, *args)
|
82
|
+
*process_args(event, aasm(state_machine_name).current_state, *args)
|
69
83
|
)
|
70
84
|
|
71
85
|
if may_fire_to = event.may_fire?(self, *args)
|
72
86
|
old_state.fire_callbacks(:before_exit, self,
|
73
|
-
*process_args(event, aasm.current_state, *args))
|
87
|
+
*process_args(event, aasm(state_machine_name).current_state, *args))
|
74
88
|
old_state.fire_callbacks(:exit, self,
|
75
|
-
*process_args(event, aasm.current_state, *args))
|
89
|
+
*process_args(event, aasm(state_machine_name).current_state, *args))
|
76
90
|
|
77
91
|
if new_state_name = event.fire(self, {:may_fire => may_fire_to}, *args)
|
78
|
-
aasm_fired(event, old_state, new_state_name, options, *args, &block)
|
92
|
+
aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args, &block)
|
79
93
|
else
|
80
|
-
aasm_failed(event_name, old_state)
|
94
|
+
aasm_failed(state_machine_name, event_name, old_state)
|
81
95
|
end
|
82
96
|
else
|
83
|
-
aasm_failed(event_name, old_state)
|
97
|
+
aasm_failed(state_machine_name, event_name, old_state)
|
84
98
|
end
|
85
99
|
rescue StandardError => e
|
86
|
-
event.fire_callbacks(:error, self, e, *process_args(event, aasm.current_state, *args)) || raise(e)
|
100
|
+
event.fire_callbacks(:error, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) || raise(e)
|
87
101
|
end
|
88
102
|
end
|
89
103
|
|
90
|
-
def aasm_fired(event, old_state, new_state_name, options, *args)
|
104
|
+
def aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args)
|
91
105
|
persist = options[:persist]
|
92
106
|
|
93
|
-
new_state = aasm.state_object_for_name(new_state_name)
|
107
|
+
new_state = aasm(state_machine_name).state_object_for_name(new_state_name)
|
94
108
|
|
95
109
|
new_state.fire_callbacks(:before_enter, self,
|
96
|
-
*process_args(event, aasm.current_state, *args))
|
110
|
+
*process_args(event, aasm(state_machine_name).current_state, *args))
|
97
111
|
|
98
112
|
new_state.fire_callbacks(:enter, self,
|
99
|
-
*process_args(event, aasm.current_state, *args)) # TODO: remove for AASM 4?
|
113
|
+
*process_args(event, aasm(state_machine_name).current_state, *args)) # TODO: remove for AASM 4?
|
100
114
|
|
101
115
|
persist_successful = true
|
102
116
|
if persist
|
103
|
-
persist_successful = aasm.set_current_state_with_persistence(new_state_name)
|
117
|
+
persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
|
104
118
|
if persist_successful
|
105
119
|
yield if block_given?
|
106
120
|
event.fire_callbacks(:success, self)
|
107
121
|
end
|
108
122
|
else
|
109
|
-
aasm.current_state = new_state_name
|
123
|
+
aasm(state_machine_name).current_state = new_state_name
|
110
124
|
yield if block_given?
|
111
125
|
end
|
112
126
|
|
113
127
|
if persist_successful
|
114
128
|
old_state.fire_callbacks(:after_exit, self,
|
115
|
-
*process_args(event, aasm.current_state, *args))
|
129
|
+
*process_args(event, aasm(state_machine_name).current_state, *args))
|
116
130
|
new_state.fire_callbacks(:after_enter, self,
|
117
|
-
*process_args(event, aasm.current_state, *args))
|
131
|
+
*process_args(event, aasm(state_machine_name).current_state, *args))
|
118
132
|
event.fire_callbacks(
|
119
133
|
:after,
|
120
134
|
self,
|
121
135
|
*process_args(event, old_state.name, *args)
|
122
136
|
)
|
123
137
|
|
124
|
-
self.aasm_event_fired(event.name, old_state.name, aasm.current_state) if self.respond_to?(:aasm_event_fired)
|
138
|
+
self.aasm_event_fired(event.name, old_state.name, aasm(state_machine_name).current_state) if self.respond_to?(:aasm_event_fired)
|
125
139
|
else
|
126
140
|
self.aasm_event_failed(event.name, old_state.name) if self.respond_to?(:aasm_event_failed)
|
127
141
|
end
|
@@ -129,13 +143,13 @@ private
|
|
129
143
|
persist_successful
|
130
144
|
end
|
131
145
|
|
132
|
-
def aasm_failed(event_name, old_state)
|
146
|
+
def aasm_failed(state_machine_name, event_name, old_state)
|
133
147
|
if self.respond_to?(:aasm_event_failed)
|
134
148
|
self.aasm_event_failed(event_name, old_state.name)
|
135
149
|
end
|
136
150
|
|
137
|
-
if AASM::StateMachine[self.class].config.whiny_transitions
|
138
|
-
raise AASM::InvalidTransition.new(self, event_name)
|
151
|
+
if AASM::StateMachine[self.class][state_machine_name].config.whiny_transitions
|
152
|
+
raise AASM::InvalidTransition.new(self, event_name, state_machine_name)
|
139
153
|
else
|
140
154
|
false
|
141
155
|
end
|
data/lib/aasm/base.rb
CHANGED
@@ -3,10 +3,12 @@ module AASM
|
|
3
3
|
|
4
4
|
attr_reader :state_machine
|
5
5
|
|
6
|
-
def initialize(klass, options={}, &block)
|
6
|
+
def initialize(klass, name, state_machine, options={}, &block)
|
7
7
|
@klass = klass
|
8
|
-
@
|
9
|
-
@state_machine
|
8
|
+
@name = name
|
9
|
+
# @state_machine = @klass.aasm(@name).state_machine
|
10
|
+
@state_machine = state_machine
|
11
|
+
@state_machine.config.column ||= (options[:column] || default_column).to_sym
|
10
12
|
# @state_machine.config.column = options[:column].to_sym if options[:column] # master
|
11
13
|
@options = options
|
12
14
|
|
@@ -31,7 +33,7 @@ module AASM
|
|
31
33
|
# and attribute is directly assigned though
|
32
34
|
@klass.class_eval %Q(
|
33
35
|
def #{@state_machine.config.column}=(state_name)
|
34
|
-
if self.class.aasm.state_machine.config.no_direct_assignment
|
36
|
+
if self.class.aasm(:#{@name}).state_machine.config.no_direct_assignment
|
35
37
|
raise AASM::NoDirectAssignmentError.new(
|
36
38
|
'direct assignment of AASM column has been disabled (see AASM configuration for this class)'
|
37
39
|
)
|
@@ -64,10 +66,16 @@ module AASM
|
|
64
66
|
def state(name, options={})
|
65
67
|
@state_machine.add_state(name, @klass, options)
|
66
68
|
|
67
|
-
@klass.
|
68
|
-
|
69
|
+
if @klass.instance_methods.include?("#{name}?")
|
70
|
+
warn "#{@klass.name}: The state name #{name} is already used!"
|
69
71
|
end
|
70
72
|
|
73
|
+
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
|
74
|
+
def #{name}?
|
75
|
+
aasm(:#{@name}).current_state == :#{name}
|
76
|
+
end
|
77
|
+
EORUBY
|
78
|
+
|
71
79
|
unless @klass.const_defined?("STATE_#{name.upcase}")
|
72
80
|
@klass.const_set("STATE_#{name.upcase}", name)
|
73
81
|
end
|
@@ -75,24 +83,30 @@ module AASM
|
|
75
83
|
|
76
84
|
# define an event
|
77
85
|
def event(name, options={}, &block)
|
78
|
-
@state_machine.
|
86
|
+
@state_machine.add_event(name, options, &block)
|
87
|
+
|
88
|
+
if @klass.instance_methods.include?("may_#{name}?".to_sym)
|
89
|
+
warn "#{@klass.name}: The event name #{name} is already used!"
|
90
|
+
end
|
79
91
|
|
80
92
|
# an addition over standard aasm so that, before firing an event, you can ask
|
81
93
|
# may_event? and get back a boolean that tells you whether the guard method
|
82
94
|
# on the transition will let this happen.
|
83
|
-
@klass.
|
84
|
-
|
85
|
-
|
95
|
+
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
|
96
|
+
def may_#{name}?(*args)
|
97
|
+
aasm(:#{@name}).may_fire_event?(:#{name}, *args)
|
98
|
+
end
|
86
99
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
100
|
+
def #{name}!(*args, &block)
|
101
|
+
aasm(:#{@name}).current_event = :#{name}!
|
102
|
+
aasm_fire_event(:#{@name}, :#{name}, {:persist => true}, *args, &block)
|
103
|
+
end
|
91
104
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
105
|
+
def #{name}(*args, &block)
|
106
|
+
aasm(:#{@name}).current_event = :#{name}
|
107
|
+
aasm_fire_event(:#{@name}, :#{name}, {:persist => false}, *args, &block)
|
108
|
+
end
|
109
|
+
EORUBY
|
96
110
|
end
|
97
111
|
|
98
112
|
def states
|
@@ -122,6 +136,10 @@ module AASM
|
|
122
136
|
|
123
137
|
private
|
124
138
|
|
139
|
+
def default_column
|
140
|
+
@name.to_sym == :default ? :aasm_state : @name.to_sym
|
141
|
+
end
|
142
|
+
|
125
143
|
def configure(key, default_value)
|
126
144
|
if @options.key?(key)
|
127
145
|
@state_machine.config.send("#{key}=", @options[key])
|
data/lib/aasm/core/event.rb
CHANGED
@@ -2,10 +2,11 @@ module AASM::Core
|
|
2
2
|
class Event
|
3
3
|
include DslHelper
|
4
4
|
|
5
|
-
attr_reader :name, :options
|
5
|
+
attr_reader :name, :state_machine, :options
|
6
6
|
|
7
|
-
def initialize(name, options = {}, &block)
|
7
|
+
def initialize(name, state_machine, options = {}, &block)
|
8
8
|
@name = name
|
9
|
+
@state_machine = state_machine
|
9
10
|
@transitions = []
|
10
11
|
@guards = Array(options[:guard] || options[:guards] || options[:if])
|
11
12
|
@unless = Array(options[:unless]) #TODO: This could use a better name
|
@@ -61,11 +62,11 @@ module AASM::Core
|
|
61
62
|
if definitions # define new transitions
|
62
63
|
# Create a separate transition for each from-state to the given state
|
63
64
|
Array(definitions[:from]).each do |s|
|
64
|
-
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
65
|
+
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
65
66
|
end
|
66
67
|
# Create a transition if :to is specified without :from (transitions from ANY state)
|
67
68
|
if @transitions.empty? && definitions[:to]
|
68
|
-
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions), &block)
|
69
|
+
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions), &block)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
@transitions
|
@@ -89,7 +90,7 @@ module AASM::Core
|
|
89
90
|
def _fire(obj, options={}, to_state=nil, *args)
|
90
91
|
result = options[:test_only] ? false : nil
|
91
92
|
if @transitions.map(&:from).any?
|
92
|
-
transitions = @transitions.select { |t| t.from == obj.aasm.current_state }
|
93
|
+
transitions = @transitions.select { |t| t.from == obj.aasm(state_machine.name).current_state }
|
93
94
|
return result if transitions.size == 0
|
94
95
|
else
|
95
96
|
transitions = @transitions
|