aasm 4.0.3 → 4.0.4

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.
@@ -0,0 +1,45 @@
1
+ module Callbacks
2
+ class WithArgs
3
+ include AASM
4
+
5
+ aasm do
6
+ state :open, :initial => true,
7
+ :before_enter => :before_enter_open,
8
+ :after_enter => :after_enter_open,
9
+ :before_exit => :before_exit_open,
10
+ :after_exit => :after_exit_open
11
+
12
+ state :closed,
13
+ :before_enter => :before_enter_closed,
14
+ :after_enter => :after_enter_closed,
15
+ :before_exit => :before_exit_closed,
16
+ :after_exit => :after_exit_closed
17
+
18
+ event :close, :before => :before, :after => :after do
19
+ transitions :to => :closed, :from => [:open], :after => :transition_proc
20
+ end
21
+
22
+ event :open, :before => :before, :after => :after do
23
+ transitions :to => :open, :from => :closed
24
+ end
25
+ end
26
+
27
+ def log(text)
28
+ # puts text
29
+ end
30
+
31
+ def before_enter_open; log('before_enter_open'); end
32
+ def before_exit_open; log('before_exit_open'); end
33
+ def after_enter_open; log('after_enter_open'); end
34
+ def after_exit_open; log('after_exit_open'); end
35
+
36
+ def before_enter_closed; log('before_enter_closed'); end
37
+ def before_exit_closed; log('before_enter_closed'); end
38
+ def after_enter_closed; log('after_enter_closed'); end
39
+ def after_exit_closed; log('after_exit_closed'); end
40
+
41
+ def before(*args); log('before'); end
42
+ def transition_proc(arg1, arg2); log('transition_proc'); end
43
+ def after(*args); log('after'); end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ module Callbacks
2
+ class WithStateArg
3
+
4
+ include AASM
5
+
6
+ aasm do
7
+ state :open, :inital => true
8
+ state :closed
9
+ state :out_to_lunch
10
+
11
+ event :close, :before => :before_method, :after => :after_method do
12
+ transitions :to => :closed, :from => [:open], :after => :transition_method
13
+ transitions :to => :out_to_lunch, :from => [:open], :after => :transition_method2
14
+ end
15
+ end
16
+
17
+ def before_method(arg); end
18
+
19
+ def after_method(arg); end
20
+
21
+ def transition_method(arg); end
22
+
23
+ def transition_method2(arg); end
24
+
25
+ end
26
+ end
@@ -2,7 +2,11 @@ class Gate < ActiveRecord::Base
2
2
  include AASM
3
3
 
4
4
  # Fake this column for testing purposes
5
- attr_accessor :aasm_state
5
+ # attr_accessor :aasm_state
6
+
7
+ def value
8
+ 'value'
9
+ end
6
10
 
7
11
  aasm do
8
12
  state :opened
@@ -14,6 +18,62 @@ class Gate < ActiveRecord::Base
14
18
  end
15
19
  end
16
20
 
21
+ class WithEnum < ActiveRecord::Base
22
+ include AASM
23
+
24
+ # Fake this column for testing purposes
25
+ attr_accessor :aasm_state
26
+
27
+ def self.test
28
+ {}
29
+ end
30
+
31
+ aasm :enum => :test do
32
+ state :opened
33
+ state :closed
34
+
35
+ event :view do
36
+ transitions :to => :read, :from => [:needs_attention]
37
+ end
38
+ end
39
+ end
40
+
41
+ class WithTrueEnum < ActiveRecord::Base
42
+ include AASM
43
+
44
+ # Fake this column for testing purposes
45
+ attr_accessor :aasm_state
46
+
47
+ def value
48
+ 'value'
49
+ end
50
+
51
+ aasm :enum => true do
52
+ state :opened
53
+ state :closed
54
+
55
+ event :view do
56
+ transitions :to => :read, :from => [:needs_attention]
57
+ end
58
+ end
59
+ end
60
+
61
+ class WithFalseEnum < ActiveRecord::Base
62
+ include AASM
63
+
64
+ # Fake this column for testing purposes
65
+ attr_accessor :aasm_state
66
+
67
+ aasm :enum => false do
68
+ state :opened
69
+ state :closed
70
+
71
+ event :view do
72
+ transitions :to => :read, :from => [:needs_attention]
73
+ end
74
+ end
75
+ end
76
+
17
77
  class Reader < ActiveRecord::Base
18
78
  include AASM
19
79
 
@@ -1,46 +1,51 @@
1
1
  require 'spec_helper'
2
+ Dir[File.dirname(__FILE__) + "/../models/callbacks/*.rb"].sort.each { |f| require File.expand_path(f) }
2
3
 
3
4
  describe 'callbacks for the new DSL' do
4
5
 
5
6
  it "be called in order" do
6
- callback = CallbackNewDsl.new
7
+ show_debug_log = false
8
+
9
+ callback = Callbacks::Basic.new(:log => show_debug_log)
7
10
  callback.aasm.current_state
8
11
 
9
- expect(callback).to receive(:before).once.ordered
10
- expect(callback).to receive(:event_guard).once.ordered.and_return(true)
11
- expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
12
- expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
13
- expect(callback).to receive(:exit_open).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(:transitioning).once.ordered
17
- expect(callback).to receive(:before_enter_closed).once.ordered
18
- expect(callback).to receive(:enter_closed).once.ordered
19
- expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
20
- expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
21
- expect(callback).to receive(:after_enter_closed).once.ordered
22
- expect(callback).to receive(:after).once.ordered
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).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
23
28
 
24
29
  # puts "------- close!"
25
30
  callback.close!
26
31
  end
27
32
 
28
33
  it "does not run any state callback if the event guard fails" do
29
- callback = CallbackNewDsl.new(:log => false)
34
+ callback = Callbacks::Basic.new(:log => false)
30
35
  callback.aasm.current_state
31
36
 
32
- expect(callback).to receive(:before).once.ordered
37
+ expect(callback).to receive(:before_event).once.ordered
33
38
  expect(callback).to receive(:event_guard).once.ordered.and_return(false)
34
39
  expect(callback).to_not receive(:transition_guard)
35
40
  expect(callback).to_not receive(:before_exit_open)
36
41
  expect(callback).to_not receive(:exit_open)
37
- expect(callback).to_not receive(:transitioning)
42
+ expect(callback).to_not receive(:after_transition)
38
43
  expect(callback).to_not receive(:before_enter_closed)
39
44
  expect(callback).to_not receive(:enter_closed)
40
45
  expect(callback).to_not receive(:aasm_write_state)
41
46
  expect(callback).to_not receive(:after_exit_open)
42
47
  expect(callback).to_not receive(:after_enter_closed)
43
- expect(callback).to_not receive(:after)
48
+ expect(callback).to_not receive(:after_event)
44
49
 
45
50
  expect {
46
51
  callback.close!
@@ -50,22 +55,22 @@ describe 'callbacks for the new DSL' do
50
55
  context "if the transition guard fails" do
51
56
  it "does not run any state callback if guard is defined inline" do
52
57
  show_debug_log = false
53
- callback = CallbackNewDsl.new(:log => show_debug_log, :fail_transition_guard => true)
58
+ callback = Callbacks::Basic.new(:log => show_debug_log, :fail_transition_guard => true)
54
59
  callback.aasm.current_state
55
60
 
56
61
  unless show_debug_log
57
- expect(callback).to receive(:before).once.ordered
62
+ expect(callback).to receive(:before_event).once.ordered
58
63
  expect(callback).to receive(:event_guard).once.ordered.and_return(true)
59
64
  expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
60
65
  expect(callback).to_not receive(:before_exit_open)
61
66
  expect(callback).to_not receive(:exit_open)
62
- expect(callback).to_not receive(:transitioning)
67
+ expect(callback).to_not receive(:after_transition)
63
68
  expect(callback).to_not receive(:before_enter_closed)
64
69
  expect(callback).to_not receive(:enter_closed)
65
70
  expect(callback).to_not receive(:aasm_write_state)
66
71
  expect(callback).to_not receive(:after_exit_open)
67
72
  expect(callback).to_not receive(:after_enter_closed)
68
- expect(callback).to_not receive(:after)
73
+ expect(callback).to_not receive(:after_event)
69
74
  end
70
75
 
71
76
  expect {
@@ -74,8 +79,6 @@ describe 'callbacks for the new DSL' do
74
79
  end
75
80
 
76
81
  it "does not run transition_guard twice for multiple permitted transitions" do
77
- require 'models/callbacks/multiple_transitions_transition_guard'
78
-
79
82
  show_debug_log = false
80
83
  callback = Callbacks::MultipleTransitionsTransitionGuard.new(:log => show_debug_log, :fail_transition_guard => true)
81
84
  callback.aasm.current_state
@@ -102,7 +105,7 @@ describe 'callbacks for the new DSL' do
102
105
  end
103
106
 
104
107
  it "does not run any state callback if guard is defined with block" do
105
- callback = GuardWithinBlock.new #(:log => true, :fail_transition_guard => true)
108
+ callback = Callbacks::GuardWithinBlock.new #(:log => true, :fail_transition_guard => true)
106
109
  callback.aasm.current_state
107
110
 
108
111
  expect(callback).to receive(:before).once.ordered
@@ -125,7 +128,7 @@ describe 'callbacks for the new DSL' do
125
128
  end
126
129
 
127
130
  it "should properly pass arguments" do
128
- cb = CallbackNewDslArgs.new
131
+ cb = Callbacks::WithArgs.new
129
132
 
130
133
  # TODO: use expect syntax here
131
134
  cb.should_receive(:before).with(:arg1, :arg2).once.ordered
@@ -141,14 +144,14 @@ describe 'callbacks for the new DSL' do
141
144
  end
142
145
 
143
146
  it "should call the callbacks given the to-state as argument" do
144
- cb = CallbackWithStateArg.new
147
+ cb = Callbacks::WithStateArg.new
145
148
  cb.should_receive(:before_method).with(:arg1).once.ordered
146
149
  cb.should_receive(:transition_method).never
147
150
  cb.should_receive(:transition_method2).with(:arg1).once.ordered
148
151
  cb.should_receive(:after_method).with(:arg1).once.ordered
149
152
  cb.close!(:out_to_lunch, :arg1)
150
153
 
151
- cb = CallbackWithStateArg.new
154
+ cb = Callbacks::WithStateArg.new
152
155
  some_object = double('some object')
153
156
  cb.should_receive(:before_method).with(some_object).once.ordered
154
157
  cb.should_receive(:transition_method2).with(some_object).once.ordered
@@ -157,14 +160,14 @@ describe 'callbacks for the new DSL' do
157
160
  end
158
161
 
159
162
  it "should call the proper methods just with arguments" do
160
- cb = CallbackWithStateArg.new
163
+ cb = Callbacks::WithStateArg.new
161
164
  cb.should_receive(:before_method).with(:arg1).once.ordered
162
165
  cb.should_receive(:transition_method).with(:arg1).once.ordered
163
166
  cb.should_receive(:transition_method).never
164
167
  cb.should_receive(:after_method).with(:arg1).once.ordered
165
168
  cb.close!(:arg1)
166
169
 
167
- cb = CallbackWithStateArg.new
170
+ cb = Callbacks::WithStateArg.new
168
171
  some_object = double('some object')
169
172
  cb.should_receive(:before_method).with(some_object).once.ordered
170
173
  cb.should_receive(:transition_method).with(some_object).once.ordered
@@ -191,7 +194,7 @@ describe 'event callbacks' do
191
194
  it "should run error_callback if an exception is raised and error_callback defined" do
192
195
  def @foo.error_callback(e); end
193
196
 
194
- allow(@foo).to receive(:before_enter).and_raise(e=StandardError.new)
197
+ allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
195
198
  expect(@foo).to receive(:error_callback).with(e)
196
199
 
197
200
  @foo.safe_close!
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe 'adding an event' do
4
4
  let(:event) do
5
- AASM::Event.new(:close_order, {:success => :success_callback}) do
5
+ AASM::Core::Event.new(:close_order, {:success => :success_callback}) do
6
6
  before :before_callback
7
7
  after :after_callback
8
8
  transitions :to => :closed, :from => [:open, :received]
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  describe 'transition inspection' do
38
38
  let(:event) do
39
- AASM::Event.new(:run) do
39
+ AASM::Core::Event.new(:run) do
40
40
  transitions :to => :running, :from => :sleeping
41
41
  end
42
42
  end
@@ -60,7 +60,7 @@ end
60
60
 
61
61
  describe 'transition inspection without from' do
62
62
  let(:event) do
63
- AASM::Event.new(:run) do
63
+ AASM::Core::Event.new(:run) do
64
64
  transitions :to => :running
65
65
  end
66
66
  end
@@ -79,12 +79,12 @@ describe 'firing an event' do
79
79
  it 'should return nil if the transitions are empty' do
80
80
  obj = double('object', :aasm => double('aasm', :current_state => 'open'))
81
81
 
82
- event = AASM::Event.new(:event)
82
+ event = AASM::Core::Event.new(:event)
83
83
  expect(event.fire(obj)).to be_nil
84
84
  end
85
85
 
86
86
  it 'should return the state of the first matching transition it finds' do
87
- event = AASM::Event.new(:event) do
87
+ event = AASM::Core::Event.new(:event) do
88
88
  transitions :to => :closed, :from => [:open, :received]
89
89
  end
90
90
 
@@ -94,7 +94,7 @@ describe 'firing an event' do
94
94
  end
95
95
 
96
96
  it 'should call the guard with the params passed in' do
97
- event = AASM::Event.new(:event) do
97
+ event = AASM::Core::Event.new(:event) do
98
98
  transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
99
99
  end
100
100
 
@@ -12,27 +12,27 @@
12
12
 
13
13
  # it "should be created without memory leak" do
14
14
  # machines_count = machines.size
15
- # state_count = number_of_objects(AASM::State)
16
- # event_count = number_of_objects(AASM::Event)
15
+ # state_count = number_of_objects(AASM::Core::State)
16
+ # event_count = number_of_objects(AASM::Core::Event)
17
17
  # puts "event_count = #{event_count}"
18
- # transition_count = number_of_objects(AASM::Transition)
18
+ # transition_count = number_of_objects(AASM::Core::Transition)
19
19
 
20
20
  # load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
21
21
  # machines.size.should == machines_count + 1 # + Process
22
22
  # number_of_objects(Models::Process).should == 0
23
- # number_of_objects(AASM::State).should == state_count + 3 # + Process
24
- # puts "event_count = #{number_of_objects(AASM::Event)}"
25
- # number_of_objects(AASM::Event).should == event_count + 2 # + Process
26
- # number_of_objects(AASM::Transition).should == transition_count + 2 # + Process
23
+ # number_of_objects(AASM::Core::State).should == state_count + 3 # + Process
24
+ # puts "event_count = #{number_of_objects(AASM::Core::Event)}"
25
+ # number_of_objects(AASM::Core::Event).should == event_count + 2 # + Process
26
+ # number_of_objects(AASM::Core::Transition).should == transition_count + 2 # + Process
27
27
 
28
28
  # Models.send(:remove_const, "Process") if Models.const_defined?("Process")
29
29
  # load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
30
30
  # machines.size.should == machines_count + 1 # + Process
31
- # number_of_objects(AASM::State).should == state_count + 3 # + Process
32
- # # ObjectSpace.each_object(AASM::Event) {|o| puts o.inspect}
33
- # puts "event_count = #{number_of_objects(AASM::Event)}"
34
- # number_of_objects(AASM::Event).should == event_count + 2 # + Process
35
- # number_of_objects(AASM::Transition).should == transition_count + 2 # + Process
31
+ # number_of_objects(AASM::Core::State).should == state_count + 3 # + Process
32
+ # # ObjectSpace.each_object(AASM::Core::Event) {|o| puts o.inspect}
33
+ # puts "event_count = #{number_of_objects(AASM::Core::Event)}"
34
+ # number_of_objects(AASM::Core::Event).should == event_count + 2 # + Process
35
+ # number_of_objects(AASM::Core::Transition).should == transition_count + 2 # + Process
36
36
  # end
37
37
 
38
38
  # end
@@ -64,58 +64,45 @@ describe "instance methods" do
64
64
  end
65
65
 
66
66
  describe "aasm_enum" do
67
- subject { lambda{ gate.send(:aasm_enum) } }
68
-
69
67
  context "when AASM enum setting contains an explicit enum method name" do
70
- let(:enum) { :test }
71
-
72
- before :each do
73
- AASM::StateMachine[Gate].config.stub(:enum).and_return(enum)
74
- end
68
+ let(:with_enum) { WithEnum.new }
75
69
 
76
70
  it "returns whatever value was set in AASM config" do
77
- expect(subject.call).to eq enum
71
+ expect(with_enum.send(:aasm_enum)).to eq :test
78
72
  end
79
73
  end
80
74
 
81
75
  context "when AASM enum setting is simply set to true" do
76
+ let(:with_true_enum) { WithTrueEnum.new }
82
77
  before :each do
83
- AASM::StateMachine[Gate].config.stub(:enum).and_return(true)
84
- Gate.aasm.stub(:attribute_name).and_return(:value)
85
- gate.stub(:aasm_guess_enum_method).and_return(:values)
78
+ WithTrueEnum.aasm.stub(:attribute_name).and_return(:value)
86
79
  end
87
80
 
88
81
  it "infers enum method name from pluralized column name" do
89
- expect(subject.call).to eq :values
90
- expect(gate).to have_received :aasm_guess_enum_method
82
+ expect(with_true_enum.send(:aasm_enum)).to eq :values
91
83
  end
92
84
  end
93
85
 
94
86
  context "when AASM enum setting is explicitly disabled" do
95
- before :each do
96
- AASM::StateMachine[Gate].config.stub(:enum).and_return(false)
97
- end
87
+ let(:with_false_enum) { WithFalseEnum.new }
98
88
 
99
89
  it "returns nil" do
100
- expect(subject.call).to be_nil
90
+ expect(with_false_enum.send(:aasm_enum)).to be_nil
101
91
  end
102
92
  end
103
93
 
104
94
  context "when AASM enum setting is not enabled" do
105
95
  before :each do
106
- AASM::StateMachine[Gate].config.stub(:enum).and_return(nil)
107
96
  Gate.aasm.stub(:attribute_name).and_return(:value)
108
97
  end
109
98
 
110
99
  context "when AASM column looks like enum" do
111
100
  before :each do
112
101
  gate.stub(:aasm_column_looks_like_enum).and_return(true)
113
- gate.stub(:aasm_guess_enum_method).and_return(:values)
114
102
  end
115
103
 
116
104
  it "infers enum method name from pluralized column name" do
117
- expect(subject.call).to eq :values
118
- expect(gate).to have_received :aasm_guess_enum_method
105
+ expect(gate.send(:aasm_enum)).to eq :values
119
106
  end
120
107
  end
121
108
 
@@ -126,7 +113,7 @@ describe "instance methods" do
126
113
  end
127
114
 
128
115
  it "returns nil, as we're not using enum" do
129
- expect(subject.call).to be_nil
116
+ expect(gate.send(:aasm_enum)).to be_nil
130
117
  end
131
118
  end
132
119
  end
@@ -265,20 +252,9 @@ describe "instance methods" do
265
252
  expect(gate.aasm.current_state).to be_nil
266
253
  end
267
254
 
268
- it "should call aasm_ensure_initial_state on validation before create" do
269
- expect(gate).to receive(:aasm_ensure_initial_state).and_return(true)
270
- gate.valid?
271
- end
272
-
273
- it "should call aasm_ensure_initial_state before create, even if skipping validations" do
274
- expect(gate).to receive(:aasm_ensure_initial_state).and_return(true)
275
- gate.save(:validate => false)
276
- end
277
-
278
- it "should not call aasm_ensure_initial_state on validation before update" do
279
- allow(gate).to receive(:new_record?).and_return(false)
280
- expect(gate).not_to receive(:aasm_ensure_initial_state)
281
- gate.valid?
255
+ it "should initialize the aasm state on instantiation" do
256
+ expect(Gate.new.aasm_state).to eql 'opened'
257
+ expect(Gate.new.aasm.current_state).to eql :opened
282
258
  end
283
259
 
284
260
  end