aasm 4.3.0 → 4.5.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/.travis.yml +4 -3
- data/CHANGELOG.md +14 -0
- data/PLANNED_CHANGES.md +1 -17
- data/README.md +58 -9
- data/gemfiles/rails_4.2_mongoid_5.gemfile +12 -0
- data/lib/aasm/base.rb +6 -2
- data/lib/aasm/core/transition.rb +1 -0
- data/lib/aasm/instance_base.rb +4 -1
- data/lib/aasm/persistence/base.rb +7 -2
- data/lib/aasm/rspec/allow_event.rb +22 -0
- data/lib/aasm/rspec/allow_transition_to.rb +22 -0
- data/lib/aasm/rspec/have_state.rb +22 -0
- data/lib/aasm/rspec/transition_from.rb +32 -0
- data/lib/aasm/rspec.rb +5 -0
- data/lib/aasm/state_machine.rb +10 -1
- data/lib/aasm/version.rb +1 -1
- data/spec/database.rb +1 -1
- data/spec/models/active_record/readme_job.rb +21 -0
- data/spec/models/callbacks/basic.rb +3 -0
- data/spec/models/callbacks/with_state_arg.rb +1 -1
- data/spec/models/callbacks/with_state_arg_multiple.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/callbacks_spec.rb +1 -0
- data/spec/unit/inspection_spec.rb +5 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +17 -0
- data/spec/unit/readme_spec.rb +42 -0
- data/spec/unit/rspec_matcher_spec.rb +79 -0
- metadata +17 -5
- /data/gemfiles/{rails_4.0_bson1.gemfile → rails_4.0_mongo_mapper.gemfile} +0 -0
- /data/gemfiles/{rails_4.1_bson1.gemfile → rails_4.1_mongo_mapper.gemfile} +0 -0
- /data/gemfiles/{rails_4.2_bson1.gemfile → rails_4.2_mongo_mapper.gemfile} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 92b6a0df28245debe06c0ecbd3bd95e91b0cf323
|
|
4
|
+
data.tar.gz: 99bfa6652b17a26388b073ee431a1878ce961a4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d6cf5a7eea74d1c20108d48370d0f6048722efefb6af0110c70de56dd13032bcaabf57749add95ae25dc086faab8cbb5dcf9ad08ad4cafbafdfb400481ce1fd4
|
|
7
|
+
data.tar.gz: 90a92ba66f2b4d67c898a9076f324e0c99ce768aa5160f6d70dc74bca48e8ba4cf95317bf5e203b66985e9dcd77a52fb814dc65cc45f498dfeab20fde31fecb8
|
data/.travis.yml
CHANGED
|
@@ -18,11 +18,12 @@ services: mongodb
|
|
|
18
18
|
gemfile:
|
|
19
19
|
- gemfiles/rails_3.2.gemfile
|
|
20
20
|
- gemfiles/rails_4.0.gemfile
|
|
21
|
-
- gemfiles/rails_4.
|
|
21
|
+
- gemfiles/rails_4.0_mongo_mapper.gemfile
|
|
22
22
|
- gemfiles/rails_4.1.gemfile
|
|
23
|
-
- gemfiles/rails_4.
|
|
23
|
+
- gemfiles/rails_4.1_mongo_mapper.gemfile
|
|
24
24
|
- gemfiles/rails_4.2.gemfile
|
|
25
|
-
- gemfiles/rails_4.
|
|
25
|
+
- gemfiles/rails_4.2_mongoid_5.gemfile
|
|
26
|
+
- gemfiles/rails_4.2_mongo_mapper.gemfile
|
|
26
27
|
|
|
27
28
|
matrix:
|
|
28
29
|
allow_failures:
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 4.5.0
|
|
4
|
+
|
|
5
|
+
* add RSpec matchers `have_state`, `allow_event` and `allow_transition_to` (see [issue #147](https://github.com/aasm/aasm/issues/147) for details)
|
|
6
|
+
* add RSpec matcher `transition_from` (see [issue #178](https://github.com/aasm/aasm/issues/178) for details, thanks to [@thomasstephane](https://github.com/thomasstephane))
|
|
7
|
+
|
|
8
|
+
## 4.4.1
|
|
9
|
+
|
|
10
|
+
* add support for rejecting certain events on inspection (see [issue #272](https://github.com/aasm/aasm/issues/272) for details, thanks to [@dubroe](https://github.com/dubroe))
|
|
11
|
+
|
|
12
|
+
## 4.4.0
|
|
13
|
+
|
|
14
|
+
* add support global transation callbacks (see [issue #221](https://github.com/aasm/aasm/issues/221) and [issue #253](https://github.com/aasm/aasm/issues/253) for details)
|
|
15
|
+
* add support (bugfix) for Mongoid >= 5.0 (see [issue #277](https://github.com/aasm/aasm/issues/277) and [issue #278](https://github.com/aasm/aasm/issues/278) for details)
|
|
16
|
+
|
|
3
17
|
## 4.3.0
|
|
4
18
|
|
|
5
19
|
* 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)
|
data/PLANNED_CHANGES.md
CHANGED
|
@@ -4,24 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
* drop support for aasm_column ?
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
# Currently working on
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
# 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
|
@@ -98,6 +98,8 @@ class Job
|
|
|
98
98
|
state :sleeping, :initial => true, :before_enter => :do_something
|
|
99
99
|
state :running
|
|
100
100
|
|
|
101
|
+
after_all_transitions :log_status_change
|
|
102
|
+
|
|
101
103
|
event :run, :after => :notify_somebody do
|
|
102
104
|
before do
|
|
103
105
|
log('Preparing to run')
|
|
@@ -117,6 +119,10 @@ class Job
|
|
|
117
119
|
end
|
|
118
120
|
end
|
|
119
121
|
|
|
122
|
+
def log_status_change
|
|
123
|
+
puts "changing from #{aasm.from_state} to #{aasm.to_state} (event: #{aasm.current_event})"
|
|
124
|
+
end
|
|
125
|
+
|
|
120
126
|
def set_process(name)
|
|
121
127
|
...
|
|
122
128
|
end
|
|
@@ -145,6 +151,7 @@ begin
|
|
|
145
151
|
transition guards
|
|
146
152
|
old_state before_exit
|
|
147
153
|
old_state exit
|
|
154
|
+
after_all_transitions
|
|
148
155
|
transition after
|
|
149
156
|
new_state before_enter
|
|
150
157
|
new_state enter
|
|
@@ -172,8 +179,9 @@ Note that when passing arguments to a state transition, the first argument must
|
|
|
172
179
|
In case of an error during the event processing the error is rescued and passed to `:error`
|
|
173
180
|
callback, which can handle it or re-raise it for further propagation.
|
|
174
181
|
|
|
175
|
-
During the transition's `:after` callback (and reliably only then
|
|
176
|
-
|
|
182
|
+
During the transition's `:after` callback (and reliably only then, or in the global
|
|
183
|
+
`after_all_transitions` callback) you can access the originating state (the from-state)
|
|
184
|
+
and the target state (the to state), like this:
|
|
177
185
|
|
|
178
186
|
```ruby
|
|
179
187
|
def set_process(name)
|
|
@@ -313,9 +321,9 @@ job.aasm.current_state # stage3
|
|
|
313
321
|
```
|
|
314
322
|
|
|
315
323
|
|
|
316
|
-
### Multiple state
|
|
324
|
+
### Multiple state machines per class
|
|
317
325
|
|
|
318
|
-
Multiple state machines per class are supported. Be aware though
|
|
326
|
+
Multiple state machines per class are supported. Be aware though that _AASM_ has been
|
|
319
327
|
built with one state machine per class in mind. Nonetheless, here's how to do it:
|
|
320
328
|
|
|
321
329
|
```ruby
|
|
@@ -365,9 +373,9 @@ simple.aasm(:work).current
|
|
|
365
373
|
|
|
366
374
|
```
|
|
367
375
|
|
|
368
|
-
_AASM_ doesn't prohibit to define the same event in
|
|
369
|
-
latest definition "wins" and overrides previous definitions.
|
|
370
|
-
`SimpleMultipleExample: The event name run is already used!`.
|
|
376
|
+
_AASM_ doesn't prohibit to define the same event in more than one state machine. The
|
|
377
|
+
latest definition "wins" and overrides previous definitions. Nonetheless, a warning is issued:
|
|
378
|
+
`SimpleMultipleExample: The aasm event name run is already used!`.
|
|
371
379
|
|
|
372
380
|
All _AASM_ class- and instance-level `aasm` methods accept a state machine selector.
|
|
373
381
|
So, for example, to use inspection on a class level, you have to use
|
|
@@ -378,7 +386,7 @@ SimpleMultipleExample.aasm(:work).states
|
|
|
378
386
|
```
|
|
379
387
|
|
|
380
388
|
*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.
|
|
389
|
+
(since version `4.3`), so please bear with us in case it doesn't work as expected.
|
|
382
390
|
|
|
383
391
|
|
|
384
392
|
|
|
@@ -417,7 +425,7 @@ job.run! # saved
|
|
|
417
425
|
|
|
418
426
|
Saving includes running all validations on the `Job` class. If you want make sure
|
|
419
427
|
the state gets saved without running validations (and thereby maybe persisting an
|
|
420
|
-
invalid object state), simply tell AASM to skip the validations. Be aware
|
|
428
|
+
invalid object state), simply tell AASM to skip the validations. Be aware that
|
|
421
429
|
when skipping validations, only the state column will be updated in the database
|
|
422
430
|
(just like ActiveRecord `change_column` is working).
|
|
423
431
|
|
|
@@ -704,9 +712,50 @@ job.aasm.states(:permitted => true).map(&:name)
|
|
|
704
712
|
# show all possible (triggerable) events (allowed by transitions)
|
|
705
713
|
job.aasm.events.map(&:name)
|
|
706
714
|
=> [:sleep]
|
|
715
|
+
job.aasm.events(:reject => :sleep).map(&:name)
|
|
716
|
+
=> []
|
|
717
|
+
|
|
718
|
+
# list states for select
|
|
719
|
+
Job.aasm.states_for_select
|
|
720
|
+
=> [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
|
|
707
721
|
```
|
|
708
722
|
|
|
709
723
|
|
|
724
|
+
### Testing
|
|
725
|
+
|
|
726
|
+
AASM provides some matchers for [RSpec](http://rspec.info): `transition_from`, `have_state`, `allow_event` and `allow_transition_to`. Add `require 'aasm/rspec'` to your `spec_helper.rb` file and use them like this
|
|
727
|
+
|
|
728
|
+
```ruby
|
|
729
|
+
# classes with only the default state machine
|
|
730
|
+
job = Job.new
|
|
731
|
+
expect(job).to transition_from(:sleeping).to(:running).on_event(:run)
|
|
732
|
+
expect(job).not_to transition_from(:sleeping).to(:cleaning).on_event(:run)
|
|
733
|
+
expect(job).to have_state(:sleeping)
|
|
734
|
+
expect(job).not_to have_state(:running)
|
|
735
|
+
expect(job).to allow_event :run
|
|
736
|
+
expect(job).to_not allow_event :clean
|
|
737
|
+
expect(job).to allow_transition_to(:running)
|
|
738
|
+
expect(job).to_not allow_transition_to(:cleaning)
|
|
739
|
+
|
|
740
|
+
# classes with multiple state machine
|
|
741
|
+
multiple = SimpleMultipleExample.new
|
|
742
|
+
expect(multiple).to transition_from(:standing).to(:walking).on_event(:walk).on(:move)
|
|
743
|
+
expect(multiple).to_not transition_from(:standing).to(:running).on_event(:walk).on(:move)
|
|
744
|
+
expect(multiple).to have_state(:standing).on(:move)
|
|
745
|
+
expect(multiple).not_to have_state(:walking).on(:move)
|
|
746
|
+
expect(multiple).to allow_event(:walk).on(:move)
|
|
747
|
+
expect(multiple).to_not allow_event(:hold).on(:move)
|
|
748
|
+
expect(multiple).to allow_transition_to(:walking).on(:move)
|
|
749
|
+
expect(multiple).to_not allow_transition_to(:running).on(:move)
|
|
750
|
+
expect(multiple).to transition_from(:sleeping).to(:processing).on_event(:start).on(:work)
|
|
751
|
+
expect(multiple).to_not transition_from(:sleeping).to(:sleeping).on_event(:start).on(:work)
|
|
752
|
+
expect(multiple).to have_state(:sleeping).on(:work)
|
|
753
|
+
expect(multiple).not_to have_state(:processing).on(:work)
|
|
754
|
+
expect(multiple).to allow_event(:start).on(:move)
|
|
755
|
+
expect(multiple).to_not allow_event(:stop).on(:move)
|
|
756
|
+
expect(multiple).to allow_transition_to(:processing).on(:move)
|
|
757
|
+
expect(multiple).to_not allow_transition_to(:sleeping).on(:move)
|
|
758
|
+
```
|
|
710
759
|
|
|
711
760
|
## <a id="installation">Installation ##
|
|
712
761
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gem "sqlite3", :platforms => :ruby
|
|
4
|
+
gem 'rubysl', :platforms => :rbx
|
|
5
|
+
gem 'rubinius-developer_tools', :platforms => :rbx
|
|
6
|
+
gem "jruby-openssl", :platforms => :jruby
|
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
|
8
|
+
gem "rails", "4.2.0"
|
|
9
|
+
gem 'mongoid', '~>5.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
10
|
+
gem 'sequel'
|
|
11
|
+
|
|
12
|
+
gemspec :path => "../"
|
data/lib/aasm/base.rb
CHANGED
|
@@ -67,7 +67,7 @@ module AASM
|
|
|
67
67
|
@state_machine.add_state(name, @klass, options)
|
|
68
68
|
|
|
69
69
|
if @klass.instance_methods.include?("#{name}?")
|
|
70
|
-
warn "#{@klass.name}: The state name #{name} is already used!"
|
|
70
|
+
warn "#{@klass.name}: The aasm state name #{name} is already used!"
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
|
|
@@ -86,7 +86,7 @@ module AASM
|
|
|
86
86
|
@state_machine.add_event(name, options, &block)
|
|
87
87
|
|
|
88
88
|
if @klass.instance_methods.include?("may_#{name}?".to_sym)
|
|
89
|
-
warn "#{@klass.name}: The event name #{name} is already used!"
|
|
89
|
+
warn "#{@klass.name}: The aasm event name #{name} is already used!"
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# an addition over standard aasm so that, before firing an event, you can ask
|
|
@@ -109,6 +109,10 @@ module AASM
|
|
|
109
109
|
EORUBY
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
+
def after_all_transitions(*callbacks, &block)
|
|
113
|
+
@state_machine.add_global_callbacks(:after_all_transitions, *callbacks, &block)
|
|
114
|
+
end
|
|
115
|
+
|
|
112
116
|
def states
|
|
113
117
|
@state_machine.states
|
|
114
118
|
end
|
data/lib/aasm/core/transition.rb
CHANGED
data/lib/aasm/instance_base.rb
CHANGED
|
@@ -49,6 +49,9 @@ module AASM
|
|
|
49
49
|
state = options[:state] || current_state
|
|
50
50
|
events = @instance.class.aasm(@name).events.select {|e| e.transitions_from_state?(state) }
|
|
51
51
|
|
|
52
|
+
options[:reject] = Array(options[:reject])
|
|
53
|
+
events.reject! { |e| options[:reject].include?(e.name) }
|
|
54
|
+
|
|
52
55
|
if options[:permitted]
|
|
53
56
|
# filters the results of events_for_current_state so that only those that
|
|
54
57
|
# are really currently possible (given transition guards) are shown.
|
|
@@ -59,7 +62,7 @@ module AASM
|
|
|
59
62
|
end
|
|
60
63
|
|
|
61
64
|
def state_object_for_name(name)
|
|
62
|
-
obj = @instance.class.aasm(@name).states.find {|s| s == name}
|
|
65
|
+
obj = @instance.class.aasm(@name).states.find {|s| s.name == name}
|
|
63
66
|
raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil?
|
|
64
67
|
obj
|
|
65
68
|
end
|
|
@@ -56,8 +56,8 @@ module AASM
|
|
|
56
56
|
def state_with_scope(name, *args)
|
|
57
57
|
state_without_scope(name, *args)
|
|
58
58
|
if @state_machine.config.create_scopes && !@klass.respond_to?(name)
|
|
59
|
-
if @klass.ancestors.map {|klass| klass.to_s}.include?("ActiveRecord::Base")
|
|
60
59
|
|
|
60
|
+
if @klass.ancestors.map {|klass| klass.to_s}.include?("ActiveRecord::Base")
|
|
61
61
|
conditions = {"#{@klass.table_name}.#{@klass.aasm(@name).attribute_name}" => name.to_s}
|
|
62
62
|
if ActiveRecord::VERSION::MAJOR >= 3
|
|
63
63
|
@klass.class_eval do
|
|
@@ -69,12 +69,17 @@ module AASM
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
elsif @klass.ancestors.map {|klass| klass.to_s}.include?("Mongoid::Document")
|
|
72
|
-
|
|
72
|
+
klass = @klass
|
|
73
|
+
state_machine_name = @name
|
|
74
|
+
scope_options = lambda {
|
|
75
|
+
klass.send(:where, {klass.aasm(state_machine_name).attribute_name.to_sym => name.to_s})
|
|
76
|
+
}
|
|
73
77
|
@klass.send(:scope, name, scope_options)
|
|
74
78
|
elsif @klass.ancestors.map {|klass| klass.to_s}.include?("MongoMapper::Document")
|
|
75
79
|
conditions = { @klass.aasm(@name).attribute_name.to_sym => name.to_s }
|
|
76
80
|
@klass.scope(name, lambda { @klass.where(conditions) })
|
|
77
81
|
end
|
|
82
|
+
|
|
78
83
|
end
|
|
79
84
|
end
|
|
80
85
|
alias_method :state_without_scope, :state
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
RSpec::Matchers.define :allow_event do |event|
|
|
2
|
+
match do |obj|
|
|
3
|
+
@state_machine_name ||= :default
|
|
4
|
+
obj.aasm(@state_machine_name).may_fire_event?(event)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
chain :on do |state_machine_name|
|
|
8
|
+
@state_machine_name = state_machine_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
description do
|
|
12
|
+
"allow event #{expected} (on :#{@state_machine_name})"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
failure_message do |obj|
|
|
16
|
+
"expected that the event :#{expected} would be allowed (on :#{@state_machine_name})"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
failure_message_when_negated do |obj|
|
|
20
|
+
"expected that the event :#{expected} would not be allowed (on :#{@state_machine_name})"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
RSpec::Matchers.define :allow_transition_to do |state|
|
|
2
|
+
match do |obj|
|
|
3
|
+
@state_machine_name ||= :default
|
|
4
|
+
obj.aasm(@state_machine_name).states(:permitted => true).include?(state)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
chain :on do |state_machine_name|
|
|
8
|
+
@state_machine_name = state_machine_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
description do
|
|
12
|
+
"allow transition to #{expected} (on :#{@state_machine_name})"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
failure_message do |obj|
|
|
16
|
+
"expected that the state :#{expected} would be reachable (on :#{@state_machine_name})"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
failure_message_when_negated do |obj|
|
|
20
|
+
"expected that the state :#{expected} would not be reachable (on :#{@state_machine_name})"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
RSpec::Matchers.define :have_state do |state|
|
|
2
|
+
match do |obj|
|
|
3
|
+
@state_machine_name ||= :default
|
|
4
|
+
obj.aasm(@state_machine_name).current_state == state.to_sym
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
chain :on do |state_machine_name|
|
|
8
|
+
@state_machine_name = state_machine_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
description do
|
|
12
|
+
"have state #{expected} (on :#{@state_machine_name})"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
failure_message do |obj|
|
|
16
|
+
"expected that :#{obj.aasm(@state_machine_name).current_state} would be :#{expected} (on :#{@state_machine_name})"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
failure_message_when_negated do |obj|
|
|
20
|
+
"expected that :#{obj.aasm(@state_machine_name).current_state} would not be :#{expected} (on :#{@state_machine_name})"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
RSpec::Matchers.define :transition_from do |from_state|
|
|
2
|
+
match do |obj|
|
|
3
|
+
@state_machine_name ||= :default
|
|
4
|
+
obj.aasm(@state_machine_name).current_state = from_state.to_sym
|
|
5
|
+
# expect(obj).to receive(:broadcast_event).with(@event.to_s, obj, from_state, @to_state)
|
|
6
|
+
obj.send(@event) && obj.aasm(@state_machine_name).current_state == @to_state.to_sym
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
chain :on do |state_machine_name|
|
|
10
|
+
@state_machine_name = state_machine_name
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
chain :to do |state|
|
|
14
|
+
@to_state = state
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
chain :on_event do |event|
|
|
18
|
+
@event = event
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
description do
|
|
22
|
+
"transition state to :#{@to_state} from :#{expected} on event :#{@event} (on :#{@state_machine_name})"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
failure_message do |obj|
|
|
26
|
+
"expected that :#{obj.aasm(@state_machine_name).current_state} would be :#{@to_state} (on :#{@state_machine_name})"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
failure_message_when_negated do |obj|
|
|
30
|
+
"expected that :#{obj.aasm(@state_machine_name).current_state} would not be :#{@to_state} (on :#{@state_machine_name})"
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/aasm/rspec.rb
ADDED
data/lib/aasm/state_machine.rb
CHANGED
|
@@ -10,12 +10,13 @@ module AASM
|
|
|
10
10
|
(@machines ||= {})[klass.to_s] = machine
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
attr_accessor :states, :events, :initial_state, :config, :name
|
|
13
|
+
attr_accessor :states, :events, :initial_state, :config, :name, :global_callbacks
|
|
14
14
|
|
|
15
15
|
def initialize(name)
|
|
16
16
|
@initial_state = nil
|
|
17
17
|
@states = []
|
|
18
18
|
@events = {}
|
|
19
|
+
@global_callbacks = {}
|
|
19
20
|
@config = AASM::Configuration.new
|
|
20
21
|
@name = name
|
|
21
22
|
end
|
|
@@ -40,6 +41,14 @@ module AASM
|
|
|
40
41
|
@events[name] = AASM::Core::Event.new(name, self, options, &block)
|
|
41
42
|
end
|
|
42
43
|
|
|
44
|
+
def add_global_callbacks(name, *callbacks, &block)
|
|
45
|
+
@global_callbacks[name] ||= []
|
|
46
|
+
callbacks.each do |callback|
|
|
47
|
+
@global_callbacks[name] << callback
|
|
48
|
+
end
|
|
49
|
+
@global_callbacks[name] << block if block
|
|
50
|
+
end
|
|
51
|
+
|
|
43
52
|
private
|
|
44
53
|
|
|
45
54
|
def set_initial_state(name, options)
|
data/lib/aasm/version.rb
CHANGED
data/spec/database.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
ActiveRecord::Migration.suppress_messages do
|
|
2
|
-
%w{gates multiple_gates readers writers transients simples no_scopes multiple_no_scopes no_direct_assignments multiple_no_direct_assignments thieves multiple_thieves localizer_test_models persisted_states provided_and_persisted_states with_enums with_true_enums with_false_enums false_states multiple_with_enums multiple_with_true_enums multiple_with_false_enums multiple_false_states}.each do |table_name|
|
|
2
|
+
%w{gates multiple_gates readers writers transients simples no_scopes multiple_no_scopes no_direct_assignments multiple_no_direct_assignments thieves multiple_thieves localizer_test_models persisted_states provided_and_persisted_states with_enums with_true_enums with_false_enums false_states multiple_with_enums multiple_with_true_enums multiple_with_false_enums multiple_false_states readme_jobs}.each do |table_name|
|
|
3
3
|
ActiveRecord::Migration.create_table table_name, :force => true do |t|
|
|
4
4
|
t.string "aasm_state"
|
|
5
5
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class ReadmeJob < ActiveRecord::Base
|
|
2
|
+
include AASM
|
|
3
|
+
|
|
4
|
+
aasm do
|
|
5
|
+
state :sleeping, :initial => true
|
|
6
|
+
state :running
|
|
7
|
+
state :cleaning
|
|
8
|
+
|
|
9
|
+
event :run do
|
|
10
|
+
transitions :from => :sleeping, :to => :running
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
event :clean do
|
|
14
|
+
transitions :from => :running, :to => :cleaning
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
event :sleep do
|
|
18
|
+
transitions :from => [:running, :cleaning], :to => :sleeping
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -18,6 +18,8 @@ module Callbacks
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
aasm do
|
|
21
|
+
after_all_transitions :after_all_transitions
|
|
22
|
+
|
|
21
23
|
state :open, :initial => true,
|
|
22
24
|
:before_enter => :before_enter_open,
|
|
23
25
|
:enter => :enter_open,
|
|
@@ -68,6 +70,7 @@ module Callbacks
|
|
|
68
70
|
def transition_guard; log('transition_guard'); !@fail_transition_guard; end
|
|
69
71
|
|
|
70
72
|
def after_transition; log('after_transition'); end
|
|
73
|
+
def after_all_transitions;log('after_all_transitions');end
|
|
71
74
|
|
|
72
75
|
def before_event; log('before_event'); end
|
|
73
76
|
def after_event; log('after_event'); end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -2,6 +2,7 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
|
|
|
2
2
|
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
|
3
3
|
require 'aasm'
|
|
4
4
|
require 'rspec'
|
|
5
|
+
require 'aasm/rspec'
|
|
5
6
|
|
|
6
7
|
# require 'ruby-debug'; Debugger.settings[:autoeval] = true; debugger; rubys_debugger = 'annoying'
|
|
7
8
|
# require 'ruby-debug/completion'
|
data/spec/unit/callbacks_spec.rb
CHANGED
|
@@ -17,6 +17,7 @@ describe 'callbacks for the new DSL' do
|
|
|
17
17
|
expect(callback).to receive(:exit_open).once.ordered
|
|
18
18
|
# expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
19
19
|
# expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
|
|
20
|
+
expect(callback).to receive(:after_all_transitions).once.ordered
|
|
20
21
|
expect(callback).to receive(:after_transition).once.ordered
|
|
21
22
|
expect(callback).to receive(:before_enter_closed).once.ordered
|
|
22
23
|
expect(callback).to receive(:enter_closed).once.ordered
|
|
@@ -103,4 +103,9 @@ describe 'permitted events' do
|
|
|
103
103
|
expect(foo.aasm.events(:permitted => true)).to include(:close)
|
|
104
104
|
expect(foo.aasm.events(:permitted => true)).not_to include(:null)
|
|
105
105
|
end
|
|
106
|
+
|
|
107
|
+
it 'should not include events in the reject option' do
|
|
108
|
+
expect(foo.aasm.events(:permitted => true, reject: :close)).not_to include(:close)
|
|
109
|
+
expect(foo.aasm.events(:permitted => true, reject: [:close])).not_to include(:close)
|
|
110
|
+
end
|
|
106
111
|
end
|
|
@@ -521,3 +521,20 @@ describe 'basic example with two state machines' do
|
|
|
521
521
|
expect(example.aasm(:sync).current_state).to eql :unsynced
|
|
522
522
|
end
|
|
523
523
|
end
|
|
524
|
+
|
|
525
|
+
describe 'testing the README examples' do
|
|
526
|
+
it 'Usage' do
|
|
527
|
+
job = ReadmeJob.new
|
|
528
|
+
|
|
529
|
+
expect(job.sleeping?).to eql true
|
|
530
|
+
expect(job.may_run?).to eql true
|
|
531
|
+
|
|
532
|
+
job.run
|
|
533
|
+
|
|
534
|
+
expect(job.running?).to eql true
|
|
535
|
+
expect(job.sleeping?).to eql false
|
|
536
|
+
expect(job.may_run?).to eql false
|
|
537
|
+
|
|
538
|
+
expect { job.run }.to raise_error(AASM::InvalidTransition)
|
|
539
|
+
end
|
|
540
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'testing the README examples' do
|
|
4
|
+
|
|
5
|
+
it 'Usage' do
|
|
6
|
+
class Job
|
|
7
|
+
include AASM
|
|
8
|
+
|
|
9
|
+
aasm do
|
|
10
|
+
state :sleeping, :initial => true
|
|
11
|
+
state :running
|
|
12
|
+
state :cleaning
|
|
13
|
+
|
|
14
|
+
event :run do
|
|
15
|
+
transitions :from => :sleeping, :to => :running
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
event :clean do
|
|
19
|
+
transitions :from => :running, :to => :cleaning
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
event :sleep do
|
|
23
|
+
transitions :from => [:running, :cleaning], :to => :sleeping
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
job = Job.new
|
|
29
|
+
|
|
30
|
+
expect(job.sleeping?).to eql true
|
|
31
|
+
expect(job.may_run?).to eql true
|
|
32
|
+
|
|
33
|
+
job.run
|
|
34
|
+
|
|
35
|
+
expect(job.running?).to eql true
|
|
36
|
+
expect(job.sleeping?).to eql false
|
|
37
|
+
expect(job.may_run?).to eql false
|
|
38
|
+
|
|
39
|
+
expect { job.run }.to raise_error(AASM::InvalidTransition)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'state machine' do
|
|
4
|
+
let(:simple) { SimpleExample.new }
|
|
5
|
+
let(:multiple) { SimpleMultipleExample.new }
|
|
6
|
+
|
|
7
|
+
describe 'transition_from' do
|
|
8
|
+
it "works for simple state machines" do
|
|
9
|
+
expect(simple).to transition_from(:initialised).to(:filled_out).on_event(:fill_out)
|
|
10
|
+
expect(simple).to_not transition_from(:initialised).to(:authorised).on_event(:fill_out)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "works for multiple state machines" do
|
|
14
|
+
expect(multiple).to transition_from(:standing).to(:walking).on_event(:walk).on(:move)
|
|
15
|
+
expect(multiple).to_not transition_from(:standing).to(:running).on_event(:walk).on(:move)
|
|
16
|
+
|
|
17
|
+
expect(multiple).to transition_from(:sleeping).to(:processing).on_event(:start).on(:work)
|
|
18
|
+
expect(multiple).to_not transition_from(:sleeping).to(:sleeping).on_event(:start).on(:work)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'allow_transition_to' do
|
|
23
|
+
it "works for simple state machines" do
|
|
24
|
+
expect(simple).to allow_transition_to(:filled_out)
|
|
25
|
+
expect(simple).to_not allow_transition_to(:authorised)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "works for multiple state machines" do
|
|
29
|
+
expect(multiple).to allow_transition_to(:walking).on(:move)
|
|
30
|
+
expect(multiple).to_not allow_transition_to(:standing).on(:move)
|
|
31
|
+
|
|
32
|
+
expect(multiple).to allow_transition_to(:processing).on(:work)
|
|
33
|
+
expect(multiple).to_not allow_transition_to(:sleeping).on(:work)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "have_state" do
|
|
38
|
+
it "works for simple state machines" do
|
|
39
|
+
expect(simple).to have_state :initialised
|
|
40
|
+
expect(simple).to_not have_state :filled_out
|
|
41
|
+
simple.fill_out
|
|
42
|
+
expect(simple).to have_state :filled_out
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "works for multiple state machines" do
|
|
46
|
+
expect(multiple).to have_state(:standing).on(:move)
|
|
47
|
+
expect(multiple).to_not have_state(:walking).on(:move)
|
|
48
|
+
multiple.walk
|
|
49
|
+
expect(multiple).to have_state(:walking).on(:move)
|
|
50
|
+
|
|
51
|
+
expect(multiple).to have_state(:sleeping).on(:work)
|
|
52
|
+
expect(multiple).to_not have_state(:processing).on(:work)
|
|
53
|
+
multiple.start
|
|
54
|
+
expect(multiple).to have_state(:processing).on(:work)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "allow_event" do
|
|
59
|
+
it "works for simple state machines" do
|
|
60
|
+
expect(simple).to allow_event :fill_out
|
|
61
|
+
expect(simple).to_not allow_event :authorise
|
|
62
|
+
simple.fill_out
|
|
63
|
+
expect(simple).to allow_event :authorise
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "works for multiple state machines" do
|
|
67
|
+
expect(multiple).to allow_event(:walk).on(:move)
|
|
68
|
+
expect(multiple).to_not allow_event(:hold).on(:move)
|
|
69
|
+
multiple.walk
|
|
70
|
+
expect(multiple).to allow_event(:hold).on(:move)
|
|
71
|
+
|
|
72
|
+
expect(multiple).to allow_event(:start).on(:work)
|
|
73
|
+
expect(multiple).to_not allow_event(:stop).on(:work)
|
|
74
|
+
multiple.start
|
|
75
|
+
expect(multiple).to allow_event(:stop).on(:work)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aasm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Barron
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2015-
|
|
13
|
+
date: 2015-11-16 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rake
|
|
@@ -92,11 +92,12 @@ files:
|
|
|
92
92
|
- callbacks.txt
|
|
93
93
|
- gemfiles/rails_3.2.gemfile
|
|
94
94
|
- gemfiles/rails_4.0.gemfile
|
|
95
|
-
- gemfiles/rails_4.
|
|
95
|
+
- gemfiles/rails_4.0_mongo_mapper.gemfile
|
|
96
96
|
- gemfiles/rails_4.1.gemfile
|
|
97
|
-
- gemfiles/rails_4.
|
|
97
|
+
- gemfiles/rails_4.1_mongo_mapper.gemfile
|
|
98
98
|
- gemfiles/rails_4.2.gemfile
|
|
99
|
-
- gemfiles/rails_4.
|
|
99
|
+
- gemfiles/rails_4.2_mongo_mapper.gemfile
|
|
100
|
+
- gemfiles/rails_4.2_mongoid_5.gemfile
|
|
100
101
|
- lib/aasm.rb
|
|
101
102
|
- lib/aasm/aasm.rb
|
|
102
103
|
- lib/aasm/base.rb
|
|
@@ -115,6 +116,11 @@ files:
|
|
|
115
116
|
- lib/aasm/persistence/mongoid_persistence.rb
|
|
116
117
|
- lib/aasm/persistence/plain_persistence.rb
|
|
117
118
|
- lib/aasm/persistence/sequel_persistence.rb
|
|
119
|
+
- lib/aasm/rspec.rb
|
|
120
|
+
- lib/aasm/rspec/allow_event.rb
|
|
121
|
+
- lib/aasm/rspec/allow_transition_to.rb
|
|
122
|
+
- lib/aasm/rspec/have_state.rb
|
|
123
|
+
- lib/aasm/rspec/transition_from.rb
|
|
118
124
|
- lib/aasm/state_machine.rb
|
|
119
125
|
- lib/aasm/version.rb
|
|
120
126
|
- spec/database.rb
|
|
@@ -132,6 +138,7 @@ files:
|
|
|
132
138
|
- spec/models/active_record/persisted_state.rb
|
|
133
139
|
- spec/models/active_record/provided_and_persisted_state.rb
|
|
134
140
|
- spec/models/active_record/reader.rb
|
|
141
|
+
- spec/models/active_record/readme_job.rb
|
|
135
142
|
- spec/models/active_record/simple_new_dsl.rb
|
|
136
143
|
- spec/models/active_record/thief.rb
|
|
137
144
|
- spec/models/active_record/transient.rb
|
|
@@ -220,7 +227,9 @@ files:
|
|
|
220
227
|
- spec/unit/persistence/mongoid_persistence_spec.rb
|
|
221
228
|
- spec/unit/persistence/sequel_persistence_multiple_spec.rb
|
|
222
229
|
- spec/unit/persistence/sequel_persistence_spec.rb
|
|
230
|
+
- spec/unit/readme_spec.rb
|
|
223
231
|
- spec/unit/reloading_spec.rb
|
|
232
|
+
- spec/unit/rspec_matcher_spec.rb
|
|
224
233
|
- spec/unit/simple_example_spec.rb
|
|
225
234
|
- spec/unit/simple_multiple_example_spec.rb
|
|
226
235
|
- spec/unit/state_spec.rb
|
|
@@ -267,6 +276,7 @@ test_files:
|
|
|
267
276
|
- spec/models/active_record/persisted_state.rb
|
|
268
277
|
- spec/models/active_record/provided_and_persisted_state.rb
|
|
269
278
|
- spec/models/active_record/reader.rb
|
|
279
|
+
- spec/models/active_record/readme_job.rb
|
|
270
280
|
- spec/models/active_record/simple_new_dsl.rb
|
|
271
281
|
- spec/models/active_record/thief.rb
|
|
272
282
|
- spec/models/active_record/transient.rb
|
|
@@ -355,7 +365,9 @@ test_files:
|
|
|
355
365
|
- spec/unit/persistence/mongoid_persistence_spec.rb
|
|
356
366
|
- spec/unit/persistence/sequel_persistence_multiple_spec.rb
|
|
357
367
|
- spec/unit/persistence/sequel_persistence_spec.rb
|
|
368
|
+
- spec/unit/readme_spec.rb
|
|
358
369
|
- spec/unit/reloading_spec.rb
|
|
370
|
+
- spec/unit/rspec_matcher_spec.rb
|
|
359
371
|
- spec/unit/simple_example_spec.rb
|
|
360
372
|
- spec/unit/simple_multiple_example_spec.rb
|
|
361
373
|
- spec/unit/state_spec.rb
|
|
File without changes
|
|
File without changes
|
|
File without changes
|