aasm 4.2.0 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|