aasm 4.0.8 → 4.5.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/.travis.yml +7 -2
- data/CHANGELOG.md +43 -2
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +6 -3
- data/LICENSE +1 -1
- data/PLANNED_CHANGES.md +8 -4
- data/README.md +171 -14
- data/aasm.gemspec +1 -5
- data/gemfiles/rails_3.2.gemfile +3 -2
- data/gemfiles/rails_4.0.gemfile +2 -6
- data/gemfiles/rails_4.0_mongo_mapper.gemfile +14 -0
- data/gemfiles/rails_4.1.gemfile +2 -6
- data/gemfiles/rails_4.1_mongo_mapper.gemfile +14 -0
- data/gemfiles/rails_4.2.gemfile +1 -5
- data/gemfiles/rails_4.2_mongo_mapper.gemfile +14 -0
- data/gemfiles/rails_4.2_mongoid_5.gemfile +12 -0
- data/lib/aasm/aasm.rb +69 -36
- data/lib/aasm/base.rb +51 -21
- data/lib/aasm/core/event.rb +7 -6
- data/lib/aasm/core/state.rb +11 -8
- data/lib/aasm/core/transition.rb +7 -5
- data/lib/aasm/errors.rb +15 -1
- data/lib/aasm/instance_base.rb +17 -13
- data/lib/aasm/localizer.rb +1 -1
- data/lib/aasm/persistence/active_record_persistence.rb +63 -73
- data/lib/aasm/persistence/base.rb +55 -20
- data/lib/aasm/persistence/mongo_mapper_persistence.rb +157 -0
- data/lib/aasm/persistence/mongoid_persistence.rb +16 -41
- data/lib/aasm/persistence/plain_persistence.rb +8 -7
- data/lib/aasm/persistence/sequel_persistence.rb +12 -9
- data/lib/aasm/persistence.rb +2 -0
- 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 +20 -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 +7 -0
- data/spec/models/active_record/false_state.rb +35 -0
- data/spec/models/active_record/gate.rb +39 -0
- data/spec/models/active_record/localizer_test_model.rb +34 -0
- data/spec/models/active_record/no_direct_assignment.rb +21 -0
- data/spec/models/active_record/no_scope.rb +21 -0
- data/spec/models/active_record/persisted_state.rb +12 -0
- data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
- data/spec/models/active_record/reader.rb +7 -0
- data/spec/models/active_record/readme_job.rb +21 -0
- data/spec/models/active_record/simple_new_dsl.rb +17 -0
- data/spec/models/active_record/thief.rb +29 -0
- data/spec/models/active_record/transient.rb +6 -0
- data/spec/models/active_record/with_enum.rb +39 -0
- data/spec/models/active_record/with_false_enum.rb +31 -0
- data/spec/models/active_record/with_true_enum.rb +39 -0
- data/spec/models/active_record/writer.rb +6 -0
- data/spec/models/basic_two_state_machines_example.rb +25 -0
- data/spec/models/callbacks/basic.rb +3 -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.rb +9 -9
- data/spec/models/callbacks/with_args_multiple.rb +61 -0
- data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +1 -1
- data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
- data/spec/models/complex_example.rb +222 -0
- data/spec/models/conversation.rb +47 -1
- data/spec/models/default_state.rb +12 -0
- data/spec/models/foo.rb +57 -0
- data/spec/models/foo_callback_multiple.rb +45 -0
- data/spec/models/guardian.rb +10 -0
- data/spec/models/guardian_multiple.rb +48 -0
- data/spec/models/initial_state_proc.rb +31 -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 +21 -0
- data/spec/models/mongo_mapper/simple_mongo_mapper.rb +23 -0
- data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +25 -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 +14 -1
- data/spec/models/no_initial_state.rb +25 -0
- data/spec/models/parametrised_event.rb +1 -1
- data/spec/models/parametrised_event_multiple.rb +29 -0
- data/spec/models/provided_state.rb +24 -0
- 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/silencer.rb +5 -0
- data/spec/models/simple_example.rb +15 -0
- data/spec/models/simple_multiple_example.rb +30 -0
- data/spec/models/state_machine_with_failed_event.rb +12 -0
- data/spec/models/sub_class.rb +7 -0
- data/spec/models/sub_class_with_more_states.rb +18 -0
- data/spec/models/super_class.rb +46 -0
- data/spec/models/transactor.rb +27 -0
- data/spec/models/valid_state_name.rb +23 -0
- data/spec/models/validator.rb +47 -0
- data/spec/spec_helper.rb +4 -4
- data/spec/unit/api_spec.rb +6 -1
- 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 +3 -2
- data/spec/unit/complex_example_spec.rb +2 -2
- 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_naming_spec.rb +2 -15
- data/spec/unit/event_spec.rb +11 -6
- data/spec/unit/guard_multiple_spec.rb +60 -0
- data/spec/unit/guard_spec.rb +12 -0
- data/spec/unit/initial_state_multiple_spec.rb +15 -0
- data/spec/unit/initial_state_spec.rb +3 -18
- data/spec/unit/inspection_multiple_spec.rb +201 -0
- data/spec/unit/inspection_spec.rb +12 -7
- data/spec/unit/localizer_spec.rb +0 -38
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +573 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +70 -13
- data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
- data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +93 -0
- 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 +20 -23
- data/spec/unit/readme_spec.rb +42 -0
- data/spec/unit/reloading_spec.rb +1 -1
- data/spec/unit/rspec_matcher_spec.rb +79 -0
- data/spec/unit/simple_example_spec.rb +26 -42
- 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/subclassing_spec.rb +10 -10
- data/spec/unit/transition_spec.rb +39 -25
- metadata +152 -23
- data/spec/models/active_record/api.rb +0 -75
- data/spec/models/argument.rb +0 -11
- data/spec/models/auth_machine.rb +0 -88
- data/spec/models/bar.rb +0 -15
- data/spec/models/father.rb +0 -21
- data/spec/models/persistence.rb +0 -164
- data/spec/models/son.rb +0 -3
- data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -152
data/spec/models/silencer.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
class Silencer
|
|
2
2
|
include AASM
|
|
3
3
|
|
|
4
|
+
# yes, this line is here on purpose
|
|
5
|
+
# by this, we test if overriding configuration options works if
|
|
6
|
+
# the state machine is "re-opened"
|
|
7
|
+
aasm :whiny_transitions => true
|
|
8
|
+
|
|
4
9
|
aasm :whiny_transitions => false do
|
|
5
10
|
state :silent, :initial => true
|
|
6
11
|
state :crying
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class SimpleExample
|
|
2
|
+
include AASM
|
|
3
|
+
aasm do
|
|
4
|
+
state :initialised, :initial => true
|
|
5
|
+
state :filled_out
|
|
6
|
+
state :authorised
|
|
7
|
+
|
|
8
|
+
event :fill_out do
|
|
9
|
+
transitions :from => :initialised, :to => :filled_out
|
|
10
|
+
end
|
|
11
|
+
event :authorise do
|
|
12
|
+
transitions :from => :filled_out, :to => :authorised
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class SimpleMultipleExample
|
|
2
|
+
include AASM
|
|
3
|
+
aasm(:move) do
|
|
4
|
+
state :standing, :initial => true
|
|
5
|
+
state :walking
|
|
6
|
+
state :running
|
|
7
|
+
|
|
8
|
+
event :walk do
|
|
9
|
+
transitions :from => :standing, :to => :walking
|
|
10
|
+
end
|
|
11
|
+
event :run do
|
|
12
|
+
transitions :from => [:standing, :walking], :to => :running
|
|
13
|
+
end
|
|
14
|
+
event :hold do
|
|
15
|
+
transitions :from => [:walking, :running], :to => :standing
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
aasm(:work) do
|
|
20
|
+
state :sleeping, :initial => true
|
|
21
|
+
state :processing
|
|
22
|
+
|
|
23
|
+
event :start do
|
|
24
|
+
transitions :from => :sleeping, :to => :processing
|
|
25
|
+
end
|
|
26
|
+
event :stop do
|
|
27
|
+
transitions :from => :processing, :to => :sleeping
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative 'super_class'
|
|
2
|
+
|
|
3
|
+
class SubClassWithMoreStates < SuperClass
|
|
4
|
+
include AASM
|
|
5
|
+
aasm do
|
|
6
|
+
state :foo
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class SubClassWithMoreStatesMultiple < SuperClassMultiple
|
|
11
|
+
include AASM
|
|
12
|
+
aasm(:left) do
|
|
13
|
+
state :foo
|
|
14
|
+
end
|
|
15
|
+
aasm(:right) do
|
|
16
|
+
state :archived
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class SuperClass
|
|
2
|
+
include AASM
|
|
3
|
+
|
|
4
|
+
aasm do
|
|
5
|
+
state :read
|
|
6
|
+
state :ended
|
|
7
|
+
|
|
8
|
+
event :foo do
|
|
9
|
+
transitions :to => :ended, :from => [:read]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def update_state
|
|
14
|
+
if may_foo?
|
|
15
|
+
foo!
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class SuperClassMultiple
|
|
21
|
+
include AASM
|
|
22
|
+
|
|
23
|
+
aasm(:left) do
|
|
24
|
+
state :read
|
|
25
|
+
state :ended
|
|
26
|
+
|
|
27
|
+
event :foo do
|
|
28
|
+
transitions :to => :ended, :from => [:read]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
aasm(:right) do
|
|
33
|
+
state :opened
|
|
34
|
+
state :closed
|
|
35
|
+
|
|
36
|
+
event :close do
|
|
37
|
+
transitions :to => :closed, :from => [:opened]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def update_state
|
|
42
|
+
if may_foo?
|
|
43
|
+
foo!
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/spec/models/transactor.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'active_record'
|
|
2
|
+
|
|
2
3
|
class Transactor < ActiveRecord::Base
|
|
3
4
|
|
|
4
5
|
belongs_to :worker
|
|
@@ -24,3 +25,29 @@ private
|
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
end
|
|
28
|
+
|
|
29
|
+
class MultipleTransactor < ActiveRecord::Base
|
|
30
|
+
|
|
31
|
+
belongs_to :worker
|
|
32
|
+
|
|
33
|
+
include AASM
|
|
34
|
+
aasm :left, :column => :status do
|
|
35
|
+
state :sleeping, :initial => true
|
|
36
|
+
state :running, :before_enter => :start_worker, :after_enter => :fail
|
|
37
|
+
|
|
38
|
+
event :run do
|
|
39
|
+
transitions :to => :running, :from => :sleeping
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def start_worker
|
|
46
|
+
worker.update_attribute(:status, 'running')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def fail
|
|
50
|
+
raise StandardError.new('failed on purpose')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class ValidStateName
|
|
2
|
+
include AASM
|
|
3
|
+
aasm do
|
|
4
|
+
state :invalid, :initial => true
|
|
5
|
+
state :valid
|
|
6
|
+
|
|
7
|
+
event :valid do
|
|
8
|
+
transitions :to => :valid, :from => [:invalid]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ValidStateNameMultiple
|
|
14
|
+
include AASM
|
|
15
|
+
aasm(:left) do
|
|
16
|
+
state :invalid, :initial => true
|
|
17
|
+
state :valid
|
|
18
|
+
|
|
19
|
+
event :valid do
|
|
20
|
+
transitions :to => :valid, :from => [:invalid]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/spec/models/validator.rb
CHANGED
|
@@ -12,6 +12,9 @@ class Validator < ActiveRecord::Base
|
|
|
12
12
|
transitions :to => :running, :from => :sleeping
|
|
13
13
|
end
|
|
14
14
|
event :sleep do
|
|
15
|
+
after_commit do |name|
|
|
16
|
+
change_name_on_sleep name
|
|
17
|
+
end
|
|
15
18
|
transitions :to => :sleeping, :from => :running
|
|
16
19
|
end
|
|
17
20
|
event :fail do
|
|
@@ -26,6 +29,50 @@ class Validator < ActiveRecord::Base
|
|
|
26
29
|
save!
|
|
27
30
|
end
|
|
28
31
|
|
|
32
|
+
def change_name_on_sleep name
|
|
33
|
+
self.name = name
|
|
34
|
+
save!
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def fail
|
|
38
|
+
raise StandardError.new('failed on purpose')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class MultipleValidator < ActiveRecord::Base
|
|
43
|
+
|
|
44
|
+
include AASM
|
|
45
|
+
aasm :left, :column => :status do
|
|
46
|
+
state :sleeping, :initial => true
|
|
47
|
+
state :running
|
|
48
|
+
state :failed, :after_enter => :fail
|
|
49
|
+
|
|
50
|
+
event :run, :after_commit => :change_name! do
|
|
51
|
+
transitions :to => :running, :from => :sleeping
|
|
52
|
+
end
|
|
53
|
+
event :sleep do
|
|
54
|
+
after_commit do |name|
|
|
55
|
+
change_name_on_sleep name
|
|
56
|
+
end
|
|
57
|
+
transitions :to => :sleeping, :from => :running
|
|
58
|
+
end
|
|
59
|
+
event :fail do
|
|
60
|
+
transitions :to => :failed, :from => [:sleeping, :running]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
validates_presence_of :name
|
|
65
|
+
|
|
66
|
+
def change_name!
|
|
67
|
+
self.name = "name changed"
|
|
68
|
+
save!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def change_name_on_sleep name
|
|
72
|
+
self.name = name
|
|
73
|
+
save!
|
|
74
|
+
end
|
|
75
|
+
|
|
29
76
|
def fail
|
|
30
77
|
raise StandardError.new('failed on purpose')
|
|
31
78
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
$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
|
-
|
|
5
4
|
require 'rspec'
|
|
6
|
-
|
|
7
|
-
require 'coveralls'
|
|
8
|
-
Coveralls.wear!
|
|
5
|
+
require 'aasm/rspec'
|
|
9
6
|
|
|
10
7
|
# require 'ruby-debug'; Debugger.settings[:autoeval] = true; debugger; rubys_debugger = 'annoying'
|
|
11
8
|
# require 'ruby-debug/completion'
|
|
12
9
|
# require 'pry'
|
|
13
10
|
|
|
11
|
+
SEQUEL_DB = defined?(JRUBY_VERSION) ? 'jdbc:sqlite::memory:' : 'sqlite:/'
|
|
12
|
+
|
|
14
13
|
def load_schema
|
|
14
|
+
require 'logger'
|
|
15
15
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
|
16
16
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
|
17
17
|
ActiveRecord::Base.establish_connection(config['sqlite3'])
|
data/spec/unit/api_spec.rb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'models/
|
|
2
|
+
require 'models/default_state.rb'
|
|
3
|
+
require 'models/provided_state.rb'
|
|
4
|
+
require 'models/active_record/persisted_state.rb'
|
|
5
|
+
require 'models/active_record/provided_and_persisted_state.rb'
|
|
6
|
+
|
|
7
|
+
load_schema
|
|
3
8
|
|
|
4
9
|
describe "reading the current state" do
|
|
5
10
|
it "uses the AASM default" do
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'on initialization' do
|
|
4
|
+
let(:example) { BasicTwoStateMachinesExample.new }
|
|
5
|
+
|
|
6
|
+
it 'should be in the initial state' do
|
|
7
|
+
expect(example.aasm(:search).current_state).to eql :initialised
|
|
8
|
+
expect(example.aasm(:sync).current_state).to eql :unsynced
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
Dir[File.dirname(__FILE__) + "/../models/callbacks/*.rb"].sort.each { |f| require File.expand_path(f) }
|
|
3
|
+
|
|
4
|
+
describe 'callbacks for the new DSL' do
|
|
5
|
+
|
|
6
|
+
it "be called in order" do
|
|
7
|
+
show_debug_log = false
|
|
8
|
+
|
|
9
|
+
callback = Callbacks::BasicMultiple.new(:log => show_debug_log)
|
|
10
|
+
callback.aasm(:left).current_state
|
|
11
|
+
|
|
12
|
+
unless show_debug_log
|
|
13
|
+
expect(callback).to receive(:before_event).once.ordered
|
|
14
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
15
|
+
expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
|
|
16
|
+
expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
|
|
17
|
+
expect(callback).to receive(:exit_open).once.ordered
|
|
18
|
+
# expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
19
|
+
# expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
|
|
20
|
+
expect(callback).to receive(:after_transition).once.ordered
|
|
21
|
+
expect(callback).to receive(:before_enter_closed).once.ordered
|
|
22
|
+
expect(callback).to receive(:enter_closed).once.ordered
|
|
23
|
+
expect(callback).to receive(:aasm_write_state).with(:closed, :left).once.ordered.and_return(true) # this is when the state changes
|
|
24
|
+
expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
|
|
25
|
+
expect(callback).to receive(:after_enter_closed).once.ordered
|
|
26
|
+
expect(callback).to receive(:after_event).once.ordered
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# puts "------- close!"
|
|
30
|
+
callback.left_close!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "does not run any state callback if the event guard fails" do
|
|
34
|
+
callback = Callbacks::BasicMultiple.new(:log => false)
|
|
35
|
+
callback.aasm(:left).current_state
|
|
36
|
+
|
|
37
|
+
expect(callback).to receive(:before_event).once.ordered
|
|
38
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(false)
|
|
39
|
+
expect(callback).to_not receive(:transition_guard)
|
|
40
|
+
expect(callback).to_not receive(:before_exit_open)
|
|
41
|
+
expect(callback).to_not receive(:exit_open)
|
|
42
|
+
expect(callback).to_not receive(:after_transition)
|
|
43
|
+
expect(callback).to_not receive(:before_enter_closed)
|
|
44
|
+
expect(callback).to_not receive(:enter_closed)
|
|
45
|
+
expect(callback).to_not receive(:aasm_write_state)
|
|
46
|
+
expect(callback).to_not receive(:after_exit_open)
|
|
47
|
+
expect(callback).to_not receive(:after_enter_closed)
|
|
48
|
+
expect(callback).to_not receive(:after_event)
|
|
49
|
+
|
|
50
|
+
expect {
|
|
51
|
+
callback.left_close!
|
|
52
|
+
}.to raise_error(AASM::InvalidTransition)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "handles private callback methods as well" do
|
|
56
|
+
show_debug_log = false
|
|
57
|
+
|
|
58
|
+
callback = Callbacks::PrivateMethodMultiple.new(:log => show_debug_log)
|
|
59
|
+
callback.aasm(:left).current_state
|
|
60
|
+
|
|
61
|
+
# puts "------- close!"
|
|
62
|
+
expect {
|
|
63
|
+
callback.close!
|
|
64
|
+
}.to_not raise_error
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "if the transition guard fails" do
|
|
68
|
+
it "does not run any state callback if guard is defined inline" do
|
|
69
|
+
show_debug_log = false
|
|
70
|
+
callback = Callbacks::BasicMultiple.new(:log => show_debug_log, :fail_transition_guard => true)
|
|
71
|
+
callback.aasm(:left).current_state
|
|
72
|
+
|
|
73
|
+
unless show_debug_log
|
|
74
|
+
expect(callback).to receive(:before_event).once.ordered
|
|
75
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
76
|
+
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
|
77
|
+
expect(callback).to_not receive(:before_exit_open)
|
|
78
|
+
expect(callback).to_not receive(:exit_open)
|
|
79
|
+
expect(callback).to_not receive(:after_transition)
|
|
80
|
+
expect(callback).to_not receive(:before_enter_closed)
|
|
81
|
+
expect(callback).to_not receive(:enter_closed)
|
|
82
|
+
expect(callback).to_not receive(:aasm_write_state)
|
|
83
|
+
expect(callback).to_not receive(:after_exit_open)
|
|
84
|
+
expect(callback).to_not receive(:after_enter_closed)
|
|
85
|
+
expect(callback).to_not receive(:after_event)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
expect {
|
|
89
|
+
callback.left_close!
|
|
90
|
+
}.to raise_error(AASM::InvalidTransition)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "does not run transition_guard twice for multiple permitted transitions" do
|
|
94
|
+
show_debug_log = false
|
|
95
|
+
callback = Callbacks::MultipleTransitionsTransitionGuardMultiple.new(:log => show_debug_log, :fail_transition_guard => true)
|
|
96
|
+
callback.aasm(:left).current_state
|
|
97
|
+
|
|
98
|
+
unless show_debug_log
|
|
99
|
+
expect(callback).to receive(:before).once.ordered
|
|
100
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
101
|
+
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
|
102
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
103
|
+
expect(callback).to receive(:before_exit_open).once.ordered
|
|
104
|
+
expect(callback).to receive(:exit_open).once.ordered
|
|
105
|
+
expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
|
106
|
+
expect(callback).to receive(:after_exit_open).once.ordered
|
|
107
|
+
expect(callback).to receive(:after).once.ordered
|
|
108
|
+
|
|
109
|
+
expect(callback).to_not receive(:transitioning)
|
|
110
|
+
expect(callback).to_not receive(:before_enter_closed)
|
|
111
|
+
expect(callback).to_not receive(:enter_closed)
|
|
112
|
+
expect(callback).to_not receive(:after_enter_closed)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
callback.close!
|
|
116
|
+
expect(callback.aasm(:left).current_state).to eql :failed
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "does not run any state callback if guard is defined with block" do
|
|
120
|
+
callback = Callbacks::GuardWithinBlockMultiple.new #(:log => true, :fail_transition_guard => true)
|
|
121
|
+
callback.aasm(:left).current_state
|
|
122
|
+
|
|
123
|
+
expect(callback).to receive(:before).once.ordered
|
|
124
|
+
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
|
125
|
+
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
|
126
|
+
expect(callback).to_not receive(:before_exit_open)
|
|
127
|
+
expect(callback).to_not receive(:exit_open)
|
|
128
|
+
expect(callback).to_not receive(:transitioning)
|
|
129
|
+
expect(callback).to_not receive(:before_enter_closed)
|
|
130
|
+
expect(callback).to_not receive(:enter_closed)
|
|
131
|
+
expect(callback).to_not receive(:aasm_write_state)
|
|
132
|
+
expect(callback).to_not receive(:after_exit_open)
|
|
133
|
+
expect(callback).to_not receive(:after_enter_closed)
|
|
134
|
+
expect(callback).to_not receive(:after)
|
|
135
|
+
|
|
136
|
+
expect {
|
|
137
|
+
callback.close!
|
|
138
|
+
}.to raise_error(AASM::InvalidTransition)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should properly pass arguments" do
|
|
143
|
+
cb = Callbacks::WithArgsMultiple.new(:log => false)
|
|
144
|
+
cb.aasm(:left).current_state
|
|
145
|
+
|
|
146
|
+
cb.reset_data
|
|
147
|
+
cb.close!(:arg1, :arg2)
|
|
148
|
+
expect(cb.data).to eql 'before(:arg1,:arg2) before_exit_open(:arg1,:arg2) transition_proc(:arg1,:arg2) before_enter_closed(:arg1,:arg2) aasm_write_state after_exit_open(:arg1,:arg2) after_enter_closed(:arg1,:arg2) after(:arg1,:arg2)'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should call the callbacks given the to-state as argument" do
|
|
152
|
+
cb = Callbacks::WithStateArgMultiple.new
|
|
153
|
+
expect(cb).to receive(:before_method).with(:arg1).once.ordered
|
|
154
|
+
expect(cb).to receive(:transition_method).never
|
|
155
|
+
expect(cb).to receive(:transition_method2).with(:arg1).once.ordered
|
|
156
|
+
expect(cb).to receive(:after_method).with(:arg1).once.ordered
|
|
157
|
+
cb.close!(:out_to_lunch, :arg1)
|
|
158
|
+
|
|
159
|
+
cb = Callbacks::WithStateArgMultiple.new
|
|
160
|
+
some_object = double('some object')
|
|
161
|
+
expect(cb).to receive(:before_method).with(some_object).once.ordered
|
|
162
|
+
expect(cb).to receive(:transition_method2).with(some_object).once.ordered
|
|
163
|
+
expect(cb).to receive(:after_method).with(some_object).once.ordered
|
|
164
|
+
cb.close!(:out_to_lunch, some_object)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should call the proper methods just with arguments" do
|
|
168
|
+
cb = Callbacks::WithStateArgMultiple.new
|
|
169
|
+
expect(cb).to receive(:before_method).with(:arg1).once.ordered
|
|
170
|
+
expect(cb).to receive(:transition_method).with(:arg1).once.ordered
|
|
171
|
+
expect(cb).to receive(:transition_method).never
|
|
172
|
+
expect(cb).to receive(:after_method).with(:arg1).once.ordered
|
|
173
|
+
cb.close!(:arg1)
|
|
174
|
+
|
|
175
|
+
cb = Callbacks::WithStateArgMultiple.new
|
|
176
|
+
some_object = double('some object')
|
|
177
|
+
expect(cb).to receive(:before_method).with(some_object).once.ordered
|
|
178
|
+
expect(cb).to receive(:transition_method).with(some_object).once.ordered
|
|
179
|
+
expect(cb).to receive(:transition_method).never
|
|
180
|
+
expect(cb).to receive(:after_method).with(some_object).once.ordered
|
|
181
|
+
cb.close!(some_object)
|
|
182
|
+
end
|
|
183
|
+
end # callbacks for the new DSL
|
|
184
|
+
|
|
185
|
+
describe 'event callbacks' do
|
|
186
|
+
describe "with an error callback defined" do
|
|
187
|
+
before do
|
|
188
|
+
class FooCallbackMultiple
|
|
189
|
+
# this hack is needed to allow testing of parameters, since RSpec
|
|
190
|
+
# destroys a method's arity when mocked
|
|
191
|
+
attr_accessor :data
|
|
192
|
+
|
|
193
|
+
aasm(:left) do
|
|
194
|
+
event :safe_close, :success => :success_callback, :error => :error_callback do
|
|
195
|
+
transitions :to => :closed, :from => [:open]
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
@foo = FooCallbackMultiple.new
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context "error_callback defined" do
|
|
204
|
+
it "should run error_callback if an exception is raised" do
|
|
205
|
+
def @foo.error_callback(e)
|
|
206
|
+
@data = [e]
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
|
|
210
|
+
|
|
211
|
+
@foo.safe_close!
|
|
212
|
+
expect(@foo.data).to eql [e]
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should run error_callback without parameters if callback does not support any" do
|
|
216
|
+
def @foo.error_callback(e)
|
|
217
|
+
@data = []
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
|
|
221
|
+
|
|
222
|
+
@foo.safe_close!('arg1', 'arg2')
|
|
223
|
+
expect(@foo.data).to eql []
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should run error_callback with parameters if callback supports them" do
|
|
227
|
+
def @foo.error_callback(e, arg1, arg2)
|
|
228
|
+
@data = [arg1, arg2]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
|
|
232
|
+
|
|
233
|
+
@foo.safe_close!('arg1', 'arg2')
|
|
234
|
+
expect(@foo.data).to eql ['arg1', 'arg2']
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "should raise NoMethodError if exception is raised and error_callback is declared but not defined" do
|
|
239
|
+
allow(@foo).to receive(:before_enter).and_raise(StandardError)
|
|
240
|
+
expect{@foo.safe_close!}.to raise_error(NoMethodError)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "should propagate an error if no error callback is declared" do
|
|
244
|
+
allow(@foo).to receive(:before_enter).and_raise("Cannot enter safe")
|
|
245
|
+
expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
describe "with aasm_event_fired defined" do
|
|
250
|
+
before do
|
|
251
|
+
@foo = FooMultiple.new
|
|
252
|
+
def @foo.aasm_event_fired(event, from, to); end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it 'should call it for successful bang fire' do
|
|
256
|
+
expect(@foo).to receive(:aasm_event_fired).with(:close, :open, :closed)
|
|
257
|
+
@foo.close!
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'should call it for successful non-bang fire' do
|
|
261
|
+
expect(@foo).to receive(:aasm_event_fired)
|
|
262
|
+
@foo.close
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it 'should not call it for failing bang fire' do
|
|
266
|
+
allow(@foo.aasm(:left)).to receive(:set_current_state_with_persistence).and_return(false)
|
|
267
|
+
expect(@foo).not_to receive(:aasm_event_fired)
|
|
268
|
+
@foo.close!
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
describe "with aasm_event_failed defined" do
|
|
273
|
+
before do
|
|
274
|
+
@foo = FooMultiple.new
|
|
275
|
+
def @foo.aasm_event_failed(event, from); end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'should call it when transition failed for bang fire' do
|
|
279
|
+
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
|
|
280
|
+
expect {@foo.null!}.to raise_error(AASM::InvalidTransition)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it 'should call it when transition failed for non-bang fire' do
|
|
284
|
+
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
|
|
285
|
+
expect {@foo.null}.to raise_error(AASM::InvalidTransition)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it 'should not call it if persist fails for bang fire' do
|
|
289
|
+
allow(@foo.aasm(:left)).to receive(:set_current_state_with_persistence).and_return(false)
|
|
290
|
+
expect(@foo).to receive(:aasm_event_failed)
|
|
291
|
+
@foo.close!
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
end # event callbacks
|
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
|
|
@@ -52,7 +53,7 @@ describe 'callbacks for the new DSL' do
|
|
|
52
53
|
}.to raise_error(AASM::InvalidTransition)
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
it "
|
|
56
|
+
it "handles private callback methods as well" do
|
|
56
57
|
show_debug_log = false
|
|
57
58
|
|
|
58
59
|
callback = Callbacks::PrivateMethod.new(:log => show_debug_log)
|
|
@@ -145,7 +146,7 @@ describe 'callbacks for the new DSL' do
|
|
|
145
146
|
|
|
146
147
|
cb.reset_data
|
|
147
148
|
cb.close!(:arg1, :arg2)
|
|
148
|
-
expect(cb.data).to eql 'before(:arg1,:arg2) before_exit_open transition_proc(:arg1,:arg2) before_enter_closed aasm_write_state after_exit_open after_enter_closed after(:arg1,:arg2)'
|
|
149
|
+
expect(cb.data).to eql 'before(:arg1,:arg2) before_exit_open(:arg1,:arg2) transition_proc(:arg1,:arg2) before_enter_closed(:arg1,:arg2) aasm_write_state after_exit_open(:arg1,:arg2) after_enter_closed(:arg1,:arg2) after(:arg1,:arg2)'
|
|
149
150
|
end
|
|
150
151
|
|
|
151
152
|
it "should call the callbacks given the to-state as argument" do
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'on initialization' do
|
|
4
|
-
let(:auth) {
|
|
4
|
+
let(:auth) {ComplexExample.new}
|
|
5
5
|
|
|
6
6
|
it 'should be in the pending state' do
|
|
7
7
|
expect(auth.aasm.current_state).to eq(:pending)
|
|
@@ -14,7 +14,7 @@ describe 'on initialization' do
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
describe 'when being unsuspended' do
|
|
17
|
-
let(:auth) {
|
|
17
|
+
let(:auth) {ComplexExample.new}
|
|
18
18
|
|
|
19
19
|
it 'should be able to be unsuspended' do
|
|
20
20
|
auth.activate!
|