aasm 3.4.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'callbacks for the new DSL' do
4
- let(:callback) {CallbackNewDsl.new}
5
4
 
6
5
  it "be called in order" do
7
- expect(callback).to receive(:exit_open).once.ordered
6
+ callback = CallbackNewDsl.new
7
+ callback.aasm.current_state
8
+
8
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)
9
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
10
17
  expect(callback).to receive(:before_enter_closed).once.ordered
11
18
  expect(callback).to receive(:enter_closed).once.ordered
12
19
  expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
@@ -14,8 +21,102 @@ describe 'callbacks for the new DSL' do
14
21
  expect(callback).to receive(:after_enter_closed).once.ordered
15
22
  expect(callback).to receive(:after).once.ordered
16
23
 
24
+ # puts "------- close!"
17
25
  callback.close!
18
26
  end
27
+
28
+ it "does not run any state callback if the event guard fails" do
29
+ callback = CallbackNewDsl.new(:log => false)
30
+ callback.aasm.current_state
31
+
32
+ expect(callback).to receive(:before).once.ordered
33
+ expect(callback).to receive(:event_guard).once.ordered.and_return(false)
34
+ expect(callback).to_not receive(:transition_guard)
35
+ expect(callback).to_not receive(:before_exit_open)
36
+ expect(callback).to_not receive(:exit_open)
37
+ expect(callback).to_not receive(:transitioning)
38
+ expect(callback).to_not receive(:before_enter_closed)
39
+ expect(callback).to_not receive(:enter_closed)
40
+ expect(callback).to_not receive(:aasm_write_state)
41
+ expect(callback).to_not receive(:after_exit_open)
42
+ expect(callback).to_not receive(:after_enter_closed)
43
+ expect(callback).to_not receive(:after)
44
+
45
+ expect {
46
+ callback.close!
47
+ }.to raise_error(AASM::InvalidTransition)
48
+ end
49
+
50
+ it "does not run any state callback if the transition guard fails" do
51
+ callback = CallbackNewDsl.new
52
+ callback.aasm.current_state
53
+
54
+ expect(callback).to receive(:before).once.ordered
55
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
56
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
57
+ expect(callback).to_not receive(:before_exit_open)
58
+ expect(callback).to_not receive(:exit_open)
59
+ expect(callback).to_not receive(:transitioning)
60
+ expect(callback).to_not receive(:before_enter_closed)
61
+ expect(callback).to_not receive(:enter_closed)
62
+ expect(callback).to_not receive(:aasm_write_state)
63
+ expect(callback).to_not receive(:after_exit_open)
64
+ expect(callback).to_not receive(:after_enter_closed)
65
+ expect(callback).to_not receive(:after)
66
+
67
+ expect {
68
+ callback.close!
69
+ }.to raise_error(AASM::InvalidTransition)
70
+ end
71
+
72
+ it "should properly pass arguments" do
73
+ cb = CallbackNewDslArgs.new
74
+
75
+ # TODO: use expect syntax here
76
+ cb.should_receive(:before).with(:arg1, :arg2).once.ordered
77
+ cb.should_receive(:before_exit_open).once.ordered # these should be before the state changes
78
+ cb.should_receive(:transition_proc).with(:arg1, :arg2).once.ordered
79
+ cb.should_receive(:before_enter_closed).once.ordered
80
+ cb.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
81
+ cb.should_receive(:after_exit_open).once.ordered # these should be after the state changes
82
+ cb.should_receive(:after_enter_closed).once.ordered
83
+ cb.should_receive(:after).with(:arg1, :arg2).once.ordered
84
+
85
+ cb.close!(:arg1, :arg2)
86
+ end
87
+
88
+ it "should call the callbacks given the to-state as argument" do
89
+ cb = CallbackWithStateArg.new
90
+ cb.should_receive(:before_method).with(:arg1).once.ordered
91
+ cb.should_receive(:transition_method).never
92
+ cb.should_receive(:transition_method2).with(:arg1).once.ordered
93
+ cb.should_receive(:after_method).with(:arg1).once.ordered
94
+ cb.close!(:out_to_lunch, :arg1)
95
+
96
+ cb = CallbackWithStateArg.new
97
+ some_object = double('some object')
98
+ cb.should_receive(:before_method).with(some_object).once.ordered
99
+ cb.should_receive(:transition_method2).with(some_object).once.ordered
100
+ cb.should_receive(:after_method).with(some_object).once.ordered
101
+ cb.close!(:out_to_lunch, some_object)
102
+ end
103
+
104
+ it "should call the proper methods just with arguments" do
105
+ cb = CallbackWithStateArg.new
106
+ cb.should_receive(:before_method).with(:arg1).once.ordered
107
+ cb.should_receive(:transition_method).with(:arg1).once.ordered
108
+ cb.should_receive(:transition_method).never
109
+ cb.should_receive(:after_method).with(:arg1).once.ordered
110
+ cb.close!(:arg1)
111
+
112
+ cb = CallbackWithStateArg.new
113
+ some_object = double('some object')
114
+ cb.should_receive(:before_method).with(some_object).once.ordered
115
+ cb.should_receive(:transition_method).with(some_object).once.ordered
116
+ cb.should_receive(:transition_method).never
117
+ cb.should_receive(:after_method).with(some_object).once.ordered
118
+ cb.close!(some_object)
119
+ end
19
120
  end
20
121
 
21
122
  describe 'event callbacks' do
@@ -35,19 +136,19 @@ describe 'event callbacks' do
35
136
  it "should run error_callback if an exception is raised and error_callback defined" do
36
137
  def @foo.error_callback(e); end
37
138
 
38
- allow(@foo).to receive(:enter).and_raise(e=StandardError.new)
139
+ allow(@foo).to receive(:before_enter).and_raise(e=StandardError.new)
39
140
  expect(@foo).to receive(:error_callback).with(e)
40
141
 
41
142
  @foo.safe_close!
42
143
  end
43
144
 
44
145
  it "should raise NoMethodError if exceptionis raised and error_callback is declared but not defined" do
45
- allow(@foo).to receive(:enter).and_raise(StandardError)
146
+ allow(@foo).to receive(:before_enter).and_raise(StandardError)
46
147
  expect{@foo.safe_close!}.to raise_error(NoMethodError)
47
148
  end
48
149
 
49
150
  it "should propagate an error if no error callback is declared" do
50
- allow(@foo).to receive(:enter).and_raise("Cannot enter safe")
151
+ allow(@foo).to receive(:before_enter).and_raise("Cannot enter safe")
51
152
  expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
52
153
  end
53
154
  end
@@ -280,24 +280,24 @@ describe 'parametrised events' do
280
280
  expect(pe.aasm.current_state).to eq(:showering)
281
281
  end
282
282
 
283
- it 'should transition to default state when on_transition invoked' do
283
+ it 'should transition to default state when :after transition invoked' do
284
284
  pe.dress!(nil, 'purple', 'dressy')
285
285
  expect(pe.aasm.current_state).to eq(:working)
286
286
  end
287
287
 
288
- it 'should call on_transition method with args' do
288
+ it 'should call :after transition method with args' do
289
289
  pe.wakeup!(:showering)
290
290
  expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
291
291
  pe.dress!(:working, 'blue', 'jeans')
292
292
  end
293
293
 
294
- it 'should call on_transition proc' do
294
+ it 'should call :after transition proc' do
295
295
  pe.wakeup!(:showering)
296
296
  expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
297
297
  pe.dress!(:dating, 'purple', 'slacks')
298
298
  end
299
299
 
300
- it 'should call on_transition with an array of methods' do
300
+ it 'should call :after transition with an array of methods' do
301
301
  pe.wakeup!(:showering)
302
302
  expect(pe).to receive(:condition_hair)
303
303
  expect(pe).to receive(:fix_hair)
@@ -24,13 +24,13 @@ describe 'inspection for common cases' do
24
24
  expect(states).to include(:closed)
25
25
  expect(states).to include(:final)
26
26
 
27
- states = foo.aasm.states(:permissible => true)
27
+ states = foo.aasm.states(:permitted => true)
28
28
  expect(states).to include(:closed)
29
29
  expect(states).not_to include(:open)
30
30
  expect(states).not_to include(:final)
31
31
 
32
32
  foo.close
33
- expect(foo.aasm.states(:permissible => true)).to be_empty
33
+ expect(foo.aasm.states(:permitted => true)).to be_empty
34
34
  end
35
35
 
36
36
  it "delivers all states for subclasses" do
@@ -39,12 +39,12 @@ describe 'inspection for common cases' do
39
39
  expect(states).to include(:closed)
40
40
  expect(states).to include(:foo)
41
41
 
42
- states = two.aasm.states(:permissible => true)
42
+ states = two.aasm.states(:permitted => true)
43
43
  expect(states).to include(:closed)
44
44
  expect(states).not_to include(:open)
45
45
 
46
46
  two.close
47
- expect(two.aasm.states(:permissible => true)).to be_empty
47
+ expect(two.aasm.states(:permitted => true)).to be_empty
48
48
  end
49
49
 
50
50
  it "delivers all events" do
@@ -96,11 +96,11 @@ describe 'aasm.from_states_for_state' do
96
96
  end
97
97
  end
98
98
 
99
- describe 'permissible events' do
99
+ describe 'permitted events' do
100
100
  let(:foo) {Foo.new}
101
101
 
102
102
  it 'work' do
103
- expect(foo.aasm.permissible_events).to include(:close)
104
- expect(foo.aasm.permissible_events).not_to include(:null)
103
+ expect(foo.aasm.events(:permitted => true)).to include(:close)
104
+ expect(foo.aasm.events(:permitted => true)).not_to include(:null)
105
105
  end
106
106
  end
@@ -3,6 +3,7 @@ require 'active_record'
3
3
  require 'logger'
4
4
  require 'i18n'
5
5
 
6
+ I18n.enforce_available_locales = false
6
7
  load_schema
7
8
 
8
9
  class LocalizerTestModel < ActiveRecord::Base
@@ -314,10 +314,28 @@ describe "named scopes with the new DSL" do
314
314
  end
315
315
 
316
316
  it "does not create scopes if requested" do
317
- expect(NoScope).not_to respond_to(:ignored_scope)
317
+ expect(NoScope).not_to respond_to(:pending)
318
318
  end
319
319
 
320
- end
320
+ end # scopes
321
+
322
+ describe "direct assignment" do
323
+ it "is allowed by default" do
324
+ obj = NoScope.create
325
+ expect(obj.aasm_state.to_sym).to eql :pending
326
+
327
+ obj.aasm_state = :running
328
+ expect(obj.aasm_state.to_sym).to eql :running
329
+ end
330
+
331
+ it "is forbidden if configured" do
332
+ obj = NoDirectAssignment.create
333
+ expect(obj.aasm_state.to_sym).to eql :pending
334
+
335
+ expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
336
+ expect(obj.aasm_state.to_sym).to eql :pending
337
+ end
338
+ end # direct assignment
321
339
 
322
340
  describe 'initial states' do
323
341
 
@@ -61,6 +61,30 @@ describe AASM::Transition do
61
61
  expect(st.opts).to eq(opts)
62
62
  end
63
63
 
64
+ it 'should set on_transition with deprecation warning' do
65
+ opts = {:from => 'foo', :to => 'bar'}
66
+ st = AASM::Transition.allocate
67
+ st.should_receive(:warn).with('[DEPRECATION] :on_transition is deprecated, use :after instead')
68
+
69
+ st.send :initialize, opts do
70
+ guard :gg
71
+ on_transition :after_callback
72
+ end
73
+
74
+ st.opts[:after].should == [:after_callback]
75
+ end
76
+
77
+ it 'should set after and guard from dsl' do
78
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
79
+ st = AASM::Transition.new(opts) do
80
+ guard :gg
81
+ after :after_callback
82
+ end
83
+
84
+ st.opts[:guard].should == ['g', :gg]
85
+ st.opts[:after].should == [:after_callback] # TODO fix this bad code coupling
86
+ end
87
+
64
88
  it 'should pass equality check if from and to are the same' do
65
89
  opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
66
90
  st = AASM::Transition.new(opts)
@@ -100,7 +124,7 @@ describe AASM::Transition, '- when performing guard checks' do
100
124
  opts = {:from => 'foo', :to => 'bar'}
101
125
  st = AASM::Transition.new(opts)
102
126
 
103
- expect(st.perform(nil)).to be_true
127
+ expect(st.allowed?(nil)).to be_true
104
128
  end
105
129
 
106
130
  it 'should call the method on the object if guard is a symbol' do
@@ -110,7 +134,17 @@ describe AASM::Transition, '- when performing guard checks' do
110
134
  obj = double('object')
111
135
  expect(obj).to receive(:test)
112
136
 
113
- st.perform(obj)
137
+ expect(st.allowed?(obj)).to be false
138
+ end
139
+
140
+ it 'should call the method on the object if unless is a symbol' do
141
+ opts = {:from => 'foo', :to => 'bar', :unless => :test}
142
+ st = AASM::Transition.new(opts)
143
+
144
+ obj = double('object')
145
+ expect(obj).to receive(:test)
146
+
147
+ expect(st.allowed?(obj)).to be true
114
148
  end
115
149
 
116
150
  it 'should call the method on the object if guard is a string' do
@@ -120,47 +154,61 @@ describe AASM::Transition, '- when performing guard checks' do
120
154
  obj = double('object')
121
155
  expect(obj).to receive(:test)
122
156
 
123
- st.perform(obj)
157
+ expect(st.allowed?(obj)).to be false
158
+ end
159
+
160
+ it 'should call the method on the object if unless is a string' do
161
+ opts = {:from => 'foo', :to => 'bar', :unless => 'test'}
162
+ st = AASM::Transition.new(opts)
163
+
164
+ obj = double('object')
165
+ expect(obj).to receive(:test)
166
+
167
+ expect(st.allowed?(obj)).to be true
124
168
  end
125
169
 
126
170
  it 'should call the proc passing the object if the guard is a proc' do
127
- opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test}}
171
+ opts = {:from => 'foo', :to => 'bar', :guard => Proc.new { test }}
128
172
  st = AASM::Transition.new(opts)
129
173
 
130
174
  obj = double('object')
131
175
  expect(obj).to receive(:test)
132
176
 
133
- st.perform(obj)
177
+ expect(st.allowed?(obj)).to be false
134
178
  end
135
179
  end
136
180
 
137
181
  describe AASM::Transition, '- when executing the transition with a Proc' do
138
182
  it 'should call a Proc on the object with args' do
139
- opts = {:from => 'foo', :to => 'bar', :on_transition => Proc.new {|o| o.test}}
183
+ opts = {:from => 'foo', :to => 'bar', :after => Proc.new {|a| test(a) }}
140
184
  st = AASM::Transition.new(opts)
141
185
  args = {:arg1 => '1', :arg2 => '2'}
142
186
  obj = double('object', :aasm => 'aasm')
143
187
 
144
- expect(opts[:on_transition]).to receive(:call).with(any_args)
188
+ obj.should_receive(:test).with(args)
145
189
 
146
190
  st.execute(obj, args)
147
191
  end
148
192
 
149
193
  it 'should call a Proc on the object without args' do
150
- opts = {:from => 'foo', :to => 'bar', :on_transition => Proc.new {||}}
194
+ # in order to test that the Proc has been called, we make sure
195
+ # that after running the :after callback the prc_object is set
196
+ prc_object = nil
197
+ prc = Proc.new { prc_object = self }
198
+
199
+ opts = {:from => 'foo', :to => 'bar', :after => prc }
151
200
  st = AASM::Transition.new(opts)
152
201
  args = {:arg1 => '1', :arg2 => '2'}
153
202
  obj = double('object', :aasm => 'aasm')
154
203
 
155
- expect(opts[:on_transition]).to receive(:call).with(no_args)
156
-
157
204
  st.execute(obj, args)
205
+ expect(prc_object).to eql obj
158
206
  end
159
207
  end
160
208
 
161
- describe AASM::Transition, '- when executing the transition with an :on_transtion method call' do
209
+ describe AASM::Transition, '- when executing the transition with an :after method call' do
162
210
  it 'should accept a String for the method name' do
163
- opts = {:from => 'foo', :to => 'bar', :on_transition => 'test'}
211
+ opts = {:from => 'foo', :to => 'bar', :after => 'test'}
164
212
  st = AASM::Transition.new(opts)
165
213
  args = {:arg1 => '1', :arg2 => '2'}
166
214
  obj = double('object', :aasm => 'aasm')
@@ -171,7 +219,7 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
171
219
  end
172
220
 
173
221
  it 'should accept a Symbol for the method name' do
174
- opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
222
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
175
223
  st = AASM::Transition.new(opts)
176
224
  args = {:arg1 => '1', :arg2 => '2'}
177
225
  obj = double('object', :aasm => 'aasm')
@@ -182,7 +230,7 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
182
230
  end
183
231
 
184
232
  it 'should pass args if the target method accepts them' do
185
- opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
233
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
186
234
  st = AASM::Transition.new(opts)
187
235
  args = {:arg1 => '1', :arg2 => '2'}
188
236
  obj = double('object', :aasm => 'aasm')
@@ -197,7 +245,7 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
197
245
  end
198
246
 
199
247
  it 'should NOT pass args if the target method does NOT accept them' do
200
- opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
248
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
201
249
  st = AASM::Transition.new(opts)
202
250
  args = {:arg1 => '1', :arg2 => '2'}
203
251
  obj = double('object', :aasm => 'aasm')
@@ -212,8 +260,8 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
212
260
  end
213
261
 
214
262
  it 'should allow accessing the from_state and the to_state' do
215
- opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
216
- st = AASM::Transition.new(opts)
263
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
264
+ transition = AASM::Transition.new(opts)
217
265
  args = {:arg1 => '1', :arg2 => '2'}
218
266
  obj = double('object', :aasm => AASM::InstanceBase.new('object'))
219
267
 
@@ -221,7 +269,7 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
221
269
  "from: #{aasm.from_state} to: #{aasm.to_state}"
222
270
  end
223
271
 
224
- return_value = st.execute(obj, args)
272
+ return_value = transition.execute(obj, args)
225
273
 
226
274
  expect(return_value).to eq('from: foo to: bar')
227
275
  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: 3.4.0
4
+ version: 4.0.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: 2014-09-12 00:00:00.000000000 Z
13
+ date: 2014-11-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -111,15 +111,20 @@ files:
111
111
  - Gemfile
112
112
  - HOWTO
113
113
  - LICENSE
114
+ - PLANNED_CHANGES.md
114
115
  - README.md
116
+ - README_FROM_VERSION_3_TO_4.md
115
117
  - Rakefile
116
118
  - aasm.gemspec
119
+ - callbacks.txt
117
120
  - gemfiles/rails_3.2.gemfile
118
121
  - gemfiles/rails_4.0.gemfile
119
122
  - gemfiles/rails_4.1.gemfile
120
123
  - lib/aasm.rb
121
124
  - lib/aasm/aasm.rb
122
125
  - lib/aasm/base.rb
126
+ - lib/aasm/configuration.rb
127
+ - lib/aasm/dsl_helper.rb
123
128
  - lib/aasm/errors.rb
124
129
  - lib/aasm/event.rb
125
130
  - lib/aasm/instance_base.rb