aasm 3.4.0 → 4.0.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.
@@ -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