runcoderun-aasm 2.0.2.1 → 2.0.2.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.
data/CHANGELOG CHANGED
@@ -1,5 +1,3 @@
1
- * call the :success callback for non-persistent state machines in addition to persistent ones [Rob Sanheim]
2
-
3
1
  * In AR persistence, move state column from class level variables into the StateMachine object for the class
4
2
 
5
3
  * allowed :to array and :on_transition callback [Kevin Triplett]
data/README.rdoc CHANGED
@@ -31,7 +31,7 @@ A release and a gem are forthcoming.
31
31
  === Building your own gems
32
32
 
33
33
  % rake gem
34
- % sudo gem install pkg/aasm-2.0.1.gem
34
+ % sudo gem install pkg/aasm-2.0.2.gem
35
35
 
36
36
 
37
37
  == Simple Example
@@ -44,19 +44,51 @@ Here's a quick example highlighting some of the features.
44
44
  aasm_initial_state :new
45
45
 
46
46
  aasm_state :new
47
- aasm_state :read
47
+ aasm_state :read, :enter => :mark_thread_as_read
48
48
  aasm_state :closed
49
49
 
50
50
 
51
51
  aasm_event :view do
52
- transitions :to => :read, :from => [:new]
52
+ # Transitions can take an optional on_transition option to execute some logic when the event is happening.
53
+ # It can take a single string or symbol (denoting a method), an array of string or symbols
54
+ # (denoting several methods), or an inline lambda
55
+ transitions :to => :read, :from => [:new], :on_transition => :set_last_read_at, :guard => :user_authorized
53
56
  end
54
57
 
55
58
  aasm_event :close do
56
59
  transitions :to => :closed, :from => [:read, :new]
57
60
  end
61
+
62
+ # Update last_read_at timestamp when the conversation is viewed
63
+ def set_last_read_at
64
+ self.last_read_at = Time.now
65
+ end
66
+
58
67
  end
59
68
 
69
+
70
+ == Explanation of transitions
71
+
72
+ The current state machine has the following process. If we were to call
73
+ <tt>Conversation#view!</tt>, we would get:
74
+
75
+ state:new
76
+ |
77
+ | <-- :exit called on state[new]
78
+ |
79
+ | <-- :guard called on state[read]
80
+ |
81
+ | <-- :on_transition called on state[read]
82
+ |
83
+ | <-- aasm_current_state set to "read"
84
+ |
85
+ | <-- :success called on state[read]
86
+ |
87
+ | <-- :enter called on state[read]
88
+ |
89
+ state:read
90
+
91
+
60
92
  = Other Stuff
61
93
 
62
94
  Author:: Scott Barron <scott at elitists dot net>
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ rescue Exception
14
14
  nil
15
15
  end
16
16
 
17
- if `ruby -Ilib -raasm -e "print AASM.Version"` =~ /([0-9.]+)$/
17
+ if `ruby -Ilib -rversion -e "print AASM::VERSION::STRING"` =~ /([0-9.]+)$/
18
18
  CURRENT_VERSION = $1
19
19
  else
20
20
  CURRENT_VERSION = '0.0.0'
@@ -23,7 +23,8 @@ $package_version = CURRENT_VERSION
23
23
 
24
24
  PKG_FILES = FileList['[A-Z]*',
25
25
  'lib/**/*.rb',
26
- 'doc/**/*'
26
+ 'doc/**/*',
27
+ 'spec/**/*'
27
28
  ]
28
29
 
29
30
  desc 'Generate documentation for the acts as state machine plugin.'
data/aasm.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ PKG_FILES = ["CHANGELOG", "MIT-LICENSE", "Rakefile", "README.rdoc", "TODO", "aasm.gemspec", "lib/aasm.rb", "lib/event.rb", "lib/persistence/active_record_persistence.rb", "lib/persistence.rb", "lib/state.rb", "lib/state_machine.rb", "lib/state_transition.rb", "lib/version.rb", "doc/jamis.rb", "spec/functional", "spec/functional/conversation.rb", "spec/functional/conversation_spec.rb", "spec/spec_helper.rb", "spec/unit", "spec/unit/aasm_spec.rb", "spec/unit/active_record_persistence_spec.rb", "spec/unit/event_spec.rb", "spec/unit/state_spec.rb", "spec/unit/state_transition_spec.rb"]
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'aasm'
5
+ s.version = "2.0.2.2"
6
+ s.summary = 'State machine mixin for Ruby objects'
7
+ s.description = <<-EOF
8
+ AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.
9
+ EOF
10
+ s.files = PKG_FILES
11
+ s.require_path = 'lib'
12
+ s.has_rdoc = true
13
+ s.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE', 'TODO', 'CHANGELOG']
14
+ s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc', '--title', 'AASM']
15
+
16
+ s.author = 'Scott Barron'
17
+ s.email = 'scott@elitists.net'
18
+ s.homepage = 'http://github.com/rubyist/aasm'
19
+ end
data/lib/aasm.rb CHANGED
@@ -4,10 +4,6 @@ require File.join(File.dirname(__FILE__), 'state_machine')
4
4
  require File.join(File.dirname(__FILE__), 'persistence')
5
5
 
6
6
  module AASM
7
- def self.Version
8
- '2.0.2.1'
9
- end
10
-
11
7
  class InvalidTransition < RuntimeError
12
8
  end
13
9
 
@@ -18,14 +14,15 @@ module AASM
18
14
  base.extend AASM::ClassMethods
19
15
  AASM::Persistence.set_persistence(base)
20
16
  AASM::StateMachine[base] = AASM::StateMachine.new('')
21
- end
22
17
 
23
- module ClassMethods
24
- def inherited(klass)
25
- AASM::StateMachine[klass] = AASM::StateMachine[self].dup
26
- super
18
+ base.class_eval do
19
+ def base.inherited(klass)
20
+ AASM::StateMachine[klass] = AASM::StateMachine[self].dup
21
+ end
27
22
  end
23
+ end
28
24
 
25
+ module ClassMethods
29
26
  def aasm_initial_state(set_state=nil)
30
27
  if set_state
31
28
  AASM::StateMachine[self].initial_state = set_state
@@ -99,14 +96,11 @@ module AASM
99
96
  end
100
97
 
101
98
  private
102
- def set_aasm_current_state_with_persistence(state)
103
- save_success = true
99
+ def aasm_current_state_with_persistence=(state)
104
100
  if self.respond_to?(:aasm_write_state) || self.private_methods.include?('aasm_write_state')
105
- save_success = aasm_write_state(state)
101
+ aasm_write_state(state)
106
102
  end
107
- self.aasm_current_state = state if save_success
108
-
109
- save_success
103
+ self.aasm_current_state = state
110
104
  end
111
105
 
112
106
  def aasm_current_state=(state)
@@ -126,24 +120,21 @@ module AASM
126
120
  new_state = self.class.aasm_events[name].fire(self, *args)
127
121
 
128
122
  unless new_state.nil?
129
- aasm_state_object_for_state(new_state).call_action(:enter, self)
130
-
131
- persist_successful = true
132
123
  if persist
133
- persist_successful = set_aasm_current_state_with_persistence(new_state)
134
- self.class.aasm_events[name].execute_success_callback(self) if persist_successful
124
+ self.aasm_current_state_with_persistence = new_state
135
125
  else
136
126
  self.aasm_current_state = new_state
137
- self.class.aasm_events[name].execute_success_callback(self)
138
127
  end
139
-
140
- if persist_successful
141
- self.aasm_event_fired(self.aasm_current_state, new_state) if self.respond_to?(:aasm_event_fired)
142
- else
143
- self.aasm_event_failed(name) if self.respond_to?(:aasm_event_failed)
128
+
129
+ self.send(self.class.aasm_events[name].success) if self.class.aasm_events[name].success
130
+
131
+ aasm_state_object_for_state(new_state).call_action(:enter, self)
132
+
133
+ if self.respond_to?(:aasm_event_fired)
134
+ self.aasm_event_fired(self.aasm_current_state, new_state)
144
135
  end
145
136
 
146
- persist_successful
137
+ true
147
138
  else
148
139
  if self.respond_to?(:aasm_event_failed)
149
140
  self.aasm_event_failed(name)
data/lib/event.rb CHANGED
@@ -32,17 +32,6 @@ module AASM
32
32
  @transitions.any? { |t| t.from == state }
33
33
  end
34
34
 
35
- def execute_success_callback(obj)
36
- case success
37
- when String, Symbol:
38
- obj.send(success)
39
- when Array:
40
- success.each { |meth| obj.send(meth) }
41
- when Proc:
42
- success.call(obj)
43
- end
44
- end
45
-
46
35
  private
47
36
  def transitions(trans_opts)
48
37
  Array(trans_opts[:from]).each do |s|
@@ -188,15 +188,7 @@ module AASM
188
188
  #
189
189
  # NOTE: intended to be called from an event
190
190
  def aasm_write_state(state)
191
- old_value = read_attribute(self.class.aasm_column)
192
- write_attribute(self.class.aasm_column, state.to_s)
193
-
194
- unless self.save
195
- write_attribute(self.class.aasm_column, old_value)
196
- return false
197
- end
198
-
199
- true
191
+ update_attribute(self.class.aasm_column, state.to_s)
200
192
  end
201
193
  end
202
194
 
@@ -21,6 +21,8 @@ module AASM
21
21
 
22
22
  def execute(obj, *args)
23
23
  case @on_transition
24
+ when Array
25
+ @on_transition.each { |t| obj.send(t, *args) }
24
26
  when Symbol, String
25
27
  obj.send(@on_transition, *args)
26
28
  when Proc
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ module AASM
2
+ module VERSION
3
+ STRING = '2.0.2.2'
4
+ end
5
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'aasm')
2
+
3
+ class Conversation
4
+ include AASM
5
+
6
+ aasm_initial_state :needs_attention
7
+
8
+ aasm_state :needs_attention
9
+ aasm_state :read
10
+ aasm_state :closed
11
+ aasm_state :awaiting_response
12
+ aasm_state :junk
13
+
14
+ aasm_event :new_message do
15
+ end
16
+
17
+ aasm_event :view do
18
+ transitions :to => :read, :from => [:needs_attention]
19
+ end
20
+
21
+ aasm_event :reply do
22
+ end
23
+
24
+ aasm_event :close do
25
+ transitions :to => :closed, :from => [:read, :awaiting_response]
26
+ end
27
+
28
+ aasm_event :junk do
29
+ transitions :to => :junk, :from => [:read]
30
+ end
31
+
32
+ aasm_event :unjunk do
33
+ end
34
+
35
+ def initialize(persister)
36
+ @persister = persister
37
+ end
38
+
39
+
40
+ private
41
+ def aasm_read_state
42
+ @persister.read_state
43
+ end
44
+
45
+ def aasm_write_state(state)
46
+ @persister.write_state(state)
47
+ end
48
+
49
+ end
@@ -0,0 +1,5 @@
1
+ describe Conversation, 'description' do
2
+ it '.aasm_states should contain all of the states' do
3
+ Conversation.aasm_states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'aasm')
@@ -0,0 +1,360 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ class Foo
4
+ include AASM
5
+ aasm_initial_state :open
6
+ aasm_state :open, :exit => :exit
7
+ aasm_state :closed, :enter => :enter
8
+
9
+ aasm_event :close, :success => :success_callback do
10
+ transitions :to => :closed, :from => [:open]
11
+ end
12
+
13
+ aasm_event :null do
14
+ transitions :to => :closed, :from => [:open], :guard => :always_false
15
+ end
16
+
17
+ def always_false
18
+ false
19
+ end
20
+
21
+ def success_callback
22
+ end
23
+
24
+ def enter
25
+ end
26
+ def exit
27
+ end
28
+ end
29
+
30
+ class Bar
31
+ include AASM
32
+
33
+ aasm_state :read
34
+ aasm_state :ended
35
+
36
+ aasm_event :foo do
37
+ transitions :to => :ended, :from => [:read]
38
+ end
39
+ end
40
+
41
+ class Baz < Bar
42
+ end
43
+
44
+
45
+ describe AASM, '- class level definitions' do
46
+ it 'should define a class level aasm_initial_state() method on its including class' do
47
+ Foo.should respond_to(:aasm_initial_state)
48
+ end
49
+
50
+ it 'should define a class level aasm_state() method on its including class' do
51
+ Foo.should respond_to(:aasm_state)
52
+ end
53
+
54
+ it 'should define a class level aasm_event() method on its including class' do
55
+ Foo.should respond_to(:aasm_event)
56
+ end
57
+
58
+ it 'should define a class level aasm_states() method on its including class' do
59
+ Foo.should respond_to(:aasm_states)
60
+ end
61
+
62
+ it 'should define a class level aasm_states_for_select() method on its including class' do
63
+ Foo.should respond_to(:aasm_states_for_select)
64
+ end
65
+
66
+ it 'should define a class level aasm_events() method on its including class' do
67
+ Foo.should respond_to(:aasm_events)
68
+ end
69
+
70
+ end
71
+
72
+
73
+ describe AASM, '- aasm_states_for_select' do
74
+ it "should return a select friendly array of states in the form of [['Friendly name', 'state_name']]" do
75
+ Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
76
+ end
77
+ end
78
+
79
+ describe AASM, '- instance level definitions' do
80
+ before(:each) do
81
+ @foo = Foo.new
82
+ end
83
+
84
+ it 'should define a state querying instance method on including class' do
85
+ @foo.should respond_to(:open?)
86
+ end
87
+
88
+ it 'should define an event! inance method' do
89
+ @foo.should respond_to(:close!)
90
+ end
91
+ end
92
+
93
+ describe AASM, '- initial states' do
94
+ before(:each) do
95
+ @foo = Foo.new
96
+ @bar = Bar.new
97
+ end
98
+
99
+ it 'should set the initial state' do
100
+ @foo.aasm_current_state.should == :open
101
+ end
102
+
103
+ it '#open? should be initially true' do
104
+ @foo.open?.should be_true
105
+ end
106
+
107
+ it '#closed? should be initially false' do
108
+ @foo.closed?.should be_false
109
+ end
110
+
111
+ it 'should use the first state defined if no initial state is given' do
112
+ @bar.aasm_current_state.should == :read
113
+ end
114
+ end
115
+
116
+ describe AASM, '- event firing with persistence' do
117
+ it 'should fire the Event' do
118
+ foo = Foo.new
119
+
120
+ Foo.aasm_events[:close].should_receive(:fire).with(foo)
121
+ foo.close!
122
+ end
123
+
124
+ it 'should update the current state' do
125
+ foo = Foo.new
126
+ foo.close!
127
+
128
+ foo.aasm_current_state.should == :closed
129
+ end
130
+
131
+ it 'should call the success callback if one was provided' do
132
+ foo = Foo.new
133
+
134
+ foo.should_receive(:success_callback)
135
+
136
+ foo.close!
137
+ end
138
+
139
+ it 'should attempt to persist if aasm_write_state is defined' do
140
+ foo = Foo.new
141
+
142
+ def foo.aasm_write_state
143
+ end
144
+
145
+ foo.should_receive(:aasm_write_state)
146
+
147
+ foo.close!
148
+ end
149
+ end
150
+
151
+ describe AASM, '- event firing without persistence' do
152
+ it 'should fire the Event' do
153
+ foo = Foo.new
154
+
155
+ Foo.aasm_events[:close].should_receive(:fire).with(foo)
156
+ foo.close
157
+ end
158
+
159
+ it 'should update the current state' do
160
+ foo = Foo.new
161
+ foo.close
162
+
163
+ foo.aasm_current_state.should == :closed
164
+ end
165
+
166
+ it 'should attempt to persist if aasm_write_state is defined' do
167
+ foo = Foo.new
168
+
169
+ def foo.aasm_write_state
170
+ end
171
+
172
+ foo.should_receive(:aasm_write_state_without_persistence)
173
+
174
+ foo.close
175
+ end
176
+ end
177
+
178
+ describe AASM, '- persistence' do
179
+ it 'should read the state if it has not been set and aasm_read_state is defined' do
180
+ foo = Foo.new
181
+ def foo.aasm_read_state
182
+ end
183
+
184
+ foo.should_receive(:aasm_read_state)
185
+
186
+ foo.aasm_current_state
187
+ end
188
+ end
189
+
190
+ describe AASM, '- getting events for a state' do
191
+ it '#aasm_events_for_current_state should use current state' do
192
+ foo = Foo.new
193
+ foo.should_receive(:aasm_current_state)
194
+ foo.aasm_events_for_current_state
195
+ end
196
+
197
+ it '#aasm_events_for_current_state should use aasm_events_for_state' do
198
+ foo = Foo.new
199
+ foo.stub!(:aasm_current_state).and_return(:foo)
200
+ foo.should_receive(:aasm_events_for_state).with(:foo)
201
+ foo.aasm_events_for_current_state
202
+ end
203
+ end
204
+
205
+ describe AASM, '- event callbacks' do
206
+ it 'should call aasm_event_fired if defined and successful for bang fire' do
207
+ foo = Foo.new
208
+ def foo.aasm_event_fired(from, to)
209
+ end
210
+
211
+ foo.should_receive(:aasm_event_fired)
212
+
213
+ foo.close!
214
+ end
215
+
216
+ it 'should call aasm_event_fired if defined and successful for non-bang fire' do
217
+ foo = Foo.new
218
+ def foo.aasm_event_fired(from, to)
219
+ end
220
+
221
+ foo.should_receive(:aasm_event_fired)
222
+
223
+ foo.close
224
+ end
225
+
226
+ it 'should call aasm_event_failed if defined and transition failed for bang fire' do
227
+ foo = Foo.new
228
+ def foo.aasm_event_failed(event)
229
+ end
230
+
231
+ foo.should_receive(:aasm_event_failed)
232
+
233
+ foo.null!
234
+ end
235
+
236
+ it 'should call aasm_event_failed if defined and transition failed for non-bang fire' do
237
+ foo = Foo.new
238
+ def foo.aasm_event_failed(event)
239
+ end
240
+
241
+ foo.should_receive(:aasm_event_failed)
242
+
243
+ foo.null
244
+ end
245
+ end
246
+
247
+ describe AASM, '- state actions' do
248
+ it "should call enter when entering state" do
249
+ foo = Foo.new
250
+ foo.should_receive(:enter)
251
+
252
+ foo.close
253
+ end
254
+
255
+ it "should call exit when exiting state" do
256
+ foo = Foo.new
257
+ foo.should_receive(:exit)
258
+
259
+ foo.close
260
+ end
261
+ end
262
+
263
+
264
+ describe Baz do
265
+ it "should have the same states as it's parent" do
266
+ Baz.aasm_states.should == Bar.aasm_states
267
+ end
268
+
269
+ it "should have the same events as it's parent" do
270
+ Baz.aasm_events.should == Bar.aasm_events
271
+ end
272
+ end
273
+
274
+
275
+ class ChetanPatil
276
+ include AASM
277
+ aasm_initial_state :sleeping
278
+ aasm_state :sleeping
279
+ aasm_state :showering
280
+ aasm_state :working
281
+ aasm_state :dating
282
+
283
+ aasm_event :wakeup do
284
+ transitions :from => :sleeping, :to => [:showering, :working]
285
+ end
286
+
287
+ aasm_event :dress do
288
+ transitions :from => :sleeping, :to => :working, :on_transition => :wear_clothes
289
+ transitions :from => :showering, :to => [:working, :dating], :on_transition => Proc.new { |obj, *args| obj.wear_clothes(*args) }
290
+ end
291
+
292
+ aasm_event :go_to_bed do
293
+ transitions :from => [:working, :dating], :to => :sleeping, :on_transition => [:take_off_clothes, :brush_teeth]
294
+ end
295
+
296
+ def wear_clothes(shirt_color, trouser_type)
297
+ end
298
+
299
+ def take_off_clothes
300
+ end
301
+
302
+ def brush_teeth
303
+ end
304
+ end
305
+
306
+
307
+ describe ChetanPatil do
308
+ it 'should transition to specified next state (sleeping to showering)' do
309
+ cp = ChetanPatil.new
310
+ cp.wakeup! :showering
311
+
312
+ cp.aasm_current_state.should == :showering
313
+ end
314
+
315
+ it 'should transition to specified next state (sleeping to working)' do
316
+ cp = ChetanPatil.new
317
+ cp.wakeup! :working
318
+
319
+ cp.aasm_current_state.should == :working
320
+ end
321
+
322
+ it 'should transition to default (first or showering) state' do
323
+ cp = ChetanPatil.new
324
+ cp.wakeup!
325
+
326
+ cp.aasm_current_state.should == :showering
327
+ end
328
+
329
+ it 'should transition to default state when on_transition invoked' do
330
+ cp = ChetanPatil.new
331
+ cp.dress!(nil, 'purple', 'dressy')
332
+
333
+ cp.aasm_current_state.should == :working
334
+ end
335
+
336
+ it 'should call on_transition method with args' do
337
+ cp = ChetanPatil.new
338
+ cp.wakeup! :showering
339
+
340
+ cp.should_receive(:wear_clothes).with('blue', 'jeans')
341
+ cp.dress! :working, 'blue', 'jeans'
342
+ end
343
+
344
+ it 'should call on_transition proc' do
345
+ cp = ChetanPatil.new
346
+ cp.wakeup! :showering
347
+
348
+ cp.should_receive(:wear_clothes).with('purple', 'slacks')
349
+ cp.dress!(:dating, 'purple', 'slacks')
350
+ end
351
+
352
+ it 'should call all on_transition methods if its an array' do
353
+ cp = ChetanPatil.new
354
+ cp.dress! :working, 'purple', 'slacks'
355
+
356
+ cp.should_receive(:take_off_clothes)
357
+ cp.should_receive(:brush_teeth)
358
+ cp.go_to_bed!
359
+ end
360
+ end
@@ -0,0 +1,212 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'aasm')
2
+
3
+ begin
4
+ require 'rubygems'
5
+ require 'active_record'
6
+
7
+ # A dummy class for mocking the activerecord connection class
8
+ class Connection
9
+ end
10
+
11
+ class FooBar < ActiveRecord::Base
12
+ include AASM
13
+
14
+ # Fake this column for testing purposes
15
+ attr_accessor :aasm_state
16
+
17
+ aasm_state :open
18
+ aasm_state :closed
19
+
20
+ aasm_event :view do
21
+ transitions :to => :read, :from => [:needs_attention]
22
+ end
23
+ end
24
+
25
+ class Fi < ActiveRecord::Base
26
+ def aasm_read_state
27
+ "fi"
28
+ end
29
+ include AASM
30
+ end
31
+
32
+ class Fo < ActiveRecord::Base
33
+ def aasm_write_state(state)
34
+ "fo"
35
+ end
36
+ include AASM
37
+ end
38
+
39
+ class Fum < ActiveRecord::Base
40
+ def aasm_write_state_without_persistence(state)
41
+ "fum"
42
+ end
43
+ include AASM
44
+ end
45
+
46
+ class June < ActiveRecord::Base
47
+ include AASM
48
+ aasm_column :status
49
+ end
50
+
51
+ class Beaver < June
52
+ end
53
+
54
+ describe "aasm model", :shared => true do
55
+ it "should include AASM::Persistence::ActiveRecordPersistence" do
56
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence)
57
+ end
58
+ it "should include AASM::Persistence::ActiveRecordPersistence::InstanceMethods" do
59
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
60
+ end
61
+ end
62
+
63
+ describe FooBar, "class methods" do
64
+ before(:each) do
65
+ @klass = FooBar
66
+ end
67
+ it_should_behave_like "aasm model"
68
+ it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do
69
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState)
70
+ end
71
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do
72
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
73
+ end
74
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do
75
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
76
+ end
77
+ end
78
+
79
+ describe Fi, "class methods" do
80
+ before(:each) do
81
+ @klass = Fi
82
+ end
83
+ it_should_behave_like "aasm model"
84
+ it "should not include AASM::Persistence::ActiveRecordPersistence::ReadState" do
85
+ @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::ReadState)
86
+ end
87
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do
88
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
89
+ end
90
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do
91
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
92
+ end
93
+ end
94
+
95
+ describe Fo, "class methods" do
96
+ before(:each) do
97
+ @klass = Fo
98
+ end
99
+ it_should_behave_like "aasm model"
100
+ it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do
101
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState)
102
+ end
103
+ it "should not include AASM::Persistence::ActiveRecordPersistence::WriteState" do
104
+ @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
105
+ end
106
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do
107
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
108
+ end
109
+ end
110
+
111
+ describe Fum, "class methods" do
112
+ before(:each) do
113
+ @klass = Fum
114
+ end
115
+ it_should_behave_like "aasm model"
116
+ it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do
117
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState)
118
+ end
119
+ it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do
120
+ @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
121
+ end
122
+ it "should not include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do
123
+ @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
124
+ end
125
+ end
126
+
127
+ describe FooBar, "instance methods" do
128
+ before(:each) do
129
+ connection = mock(Connection, :columns => [])
130
+ FooBar.stub!(:connection).and_return(connection)
131
+ end
132
+
133
+ it "should respond to aasm read state when not previously defined" do
134
+ FooBar.new.should respond_to(:aasm_read_state)
135
+ end
136
+
137
+ it "should respond to aasm write state when not previously defined" do
138
+ FooBar.new.should respond_to(:aasm_write_state)
139
+ end
140
+
141
+ it "should respond to aasm write state without persistence when not previously defined" do
142
+ FooBar.new.should respond_to(:aasm_write_state_without_persistence)
143
+ end
144
+
145
+ it "should return the initial state when new and the aasm field is nil" do
146
+ FooBar.new.aasm_current_state.should == :open
147
+ end
148
+
149
+ it "should return the aasm column when new and the aasm field is not nil" do
150
+ foo = FooBar.new
151
+ foo.aasm_state = "closed"
152
+ foo.aasm_current_state.should == :closed
153
+ end
154
+
155
+ it "should return the aasm column when not new and the aasm_column is not nil" do
156
+ foo = FooBar.new
157
+ foo.stub!(:new_record?).and_return(false)
158
+ foo.aasm_state = "state"
159
+ foo.aasm_current_state.should == :state
160
+ end
161
+
162
+ it "should allow a nil state" do
163
+ foo = FooBar.new
164
+ foo.stub!(:new_record?).and_return(false)
165
+ foo.aasm_state = nil
166
+ foo.aasm_current_state.should be_nil
167
+ end
168
+
169
+ it "should have aasm_ensure_initial_state" do
170
+ foo = FooBar.new
171
+ foo.send :aasm_ensure_initial_state
172
+ end
173
+
174
+ it "should call aasm_ensure_initial_state on validation before create" do
175
+ foo = FooBar.new
176
+ foo.should_receive(:aasm_ensure_initial_state).and_return(true)
177
+ foo.valid?
178
+ end
179
+
180
+ it "should call aasm_ensure_initial_state on validation before create" do
181
+ foo = FooBar.new
182
+ foo.stub!(:new_record?).and_return(false)
183
+ foo.should_not_receive(:aasm_ensure_initial_state)
184
+ foo.valid?
185
+ end
186
+
187
+ end
188
+
189
+ describe 'Beavers' do
190
+ it "should have the same states as it's parent" do
191
+ Beaver.aasm_states.should == June.aasm_states
192
+ end
193
+
194
+ it "should have the same events as it's parent" do
195
+ Beaver.aasm_events.should == June.aasm_events
196
+ end
197
+
198
+ it "should have the same column as it's parent" do
199
+ Beaver.aasm_column.should == :status
200
+ end
201
+ end
202
+
203
+
204
+ # TODO: figure out how to test ActiveRecord reload! without a database
205
+
206
+ rescue LoadError => e
207
+ if e.message == "no such file to load -- active_record"
208
+ puts "You must install active record to run this spec. Install with sudo gem install activerecord"
209
+ else
210
+ raise
211
+ end
212
+ end
@@ -0,0 +1,51 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe AASM::SupportingClasses::Event do
4
+ before(:each) do
5
+ @name = :close_order
6
+ @success = :success_callback
7
+ end
8
+
9
+ def new_event
10
+ @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do
11
+ transitions :to => :closed, :from => [:open, :received]
12
+ end
13
+ end
14
+
15
+ it 'should set the name' do
16
+ new_event
17
+ @event.name.should == @name
18
+ end
19
+
20
+ it 'should set the success option' do
21
+ new_event
22
+ @event.success.should == @success
23
+ end
24
+
25
+ it 'should create StateTransitions' do
26
+ AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :open})
27
+ AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :received})
28
+ new_event
29
+ end
30
+ end
31
+
32
+ describe AASM::SupportingClasses::Event, 'when firing an event' do
33
+ it 'should raise an AASM::InvalidTransition error if the transitions are empty' do
34
+ obj = mock('object')
35
+ obj.stub!(:aasm_current_state)
36
+
37
+ event = AASM::SupportingClasses::Event.new(:event)
38
+ lambda { event.fire(obj) }.should raise_error(AASM::InvalidTransition)
39
+ end
40
+
41
+ it 'should return the state of the first matching transition it finds' do
42
+ event = AASM::SupportingClasses::Event.new(:event) do
43
+ transitions :to => :closed, :from => [:open, :received]
44
+ end
45
+
46
+ obj = mock('object')
47
+ obj.stub!(:aasm_current_state).and_return(:open)
48
+
49
+ event.fire(obj).should == :closed
50
+ end
51
+ end
@@ -0,0 +1,62 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ # TODO These are specs ported from original aasm
4
+ describe AASM::SupportingClasses::State do
5
+ before(:each) do
6
+ @name = :astate
7
+ @options = { :crazy_custom_key => 'key' }
8
+ end
9
+
10
+ def new_state(options={})
11
+ AASM::SupportingClasses::State.new(@name, @options.merge(options))
12
+ end
13
+
14
+ it 'should set the name' do
15
+ state = new_state
16
+
17
+ state.name.should == :astate
18
+ end
19
+
20
+ it 'should set the options and expose them as options' do
21
+ state = new_state
22
+
23
+ state.options.should == @options
24
+ end
25
+
26
+ it 'should be equal to a symbol of the same name' do
27
+ state = new_state
28
+
29
+ state.should == :astate
30
+ end
31
+
32
+ it 'should be equal to a State of the same name' do
33
+ new_state.should == new_state
34
+ end
35
+
36
+ it 'should send a message to the record for an action if the action is present as a symbol' do
37
+ state = new_state(:entering => :foo)
38
+
39
+ record = mock('record')
40
+ record.should_receive(:foo)
41
+
42
+ state.call_action(:entering, record)
43
+ end
44
+
45
+ it 'should send a message to the record for an action if the action is present as a string' do
46
+ state = new_state(:entering => 'foo')
47
+
48
+ record = mock('record')
49
+ record.should_receive(:foo)
50
+
51
+ state.call_action(:entering, record)
52
+ end
53
+
54
+ it 'should call a proc, passing in the record for an action if the action is present' do
55
+ state = new_state(:entering => Proc.new {|r| r.foobar})
56
+
57
+ record = mock('record')
58
+ record.should_receive(:foobar)
59
+
60
+ state.call_action(:entering, record)
61
+ end
62
+ end
@@ -0,0 +1,84 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe AASM::SupportingClasses::StateTransition do
4
+ it 'should set from, to, and opts attr readers' do
5
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
6
+ st = AASM::SupportingClasses::StateTransition.new(opts)
7
+
8
+ st.from.should == opts[:from]
9
+ st.to.should == opts[:to]
10
+ st.opts.should == opts
11
+ end
12
+
13
+ it 'should pass equality check if from and to are the same' do
14
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
15
+ st = AASM::SupportingClasses::StateTransition.new(opts)
16
+
17
+ obj = mock('object')
18
+ obj.stub!(:from).and_return(opts[:from])
19
+ obj.stub!(:to).and_return(opts[:to])
20
+
21
+ st.should == obj
22
+ end
23
+
24
+ it 'should fail equality check if from are not the same' do
25
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
26
+ st = AASM::SupportingClasses::StateTransition.new(opts)
27
+
28
+ obj = mock('object')
29
+ obj.stub!(:from).and_return('blah')
30
+ obj.stub!(:to).and_return(opts[:to])
31
+
32
+ st.should_not == obj
33
+ end
34
+
35
+ it 'should fail equality check if to are not the same' do
36
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
37
+ st = AASM::SupportingClasses::StateTransition.new(opts)
38
+
39
+ obj = mock('object')
40
+ obj.stub!(:from).and_return(opts[:from])
41
+ obj.stub!(:to).and_return('blah')
42
+
43
+ st.should_not == obj
44
+ end
45
+ end
46
+
47
+ describe AASM::SupportingClasses::StateTransition, '- when performing guard checks' do
48
+ it 'should return true of there is no guard' do
49
+ opts = {:from => 'foo', :to => 'bar'}
50
+ st = AASM::SupportingClasses::StateTransition.new(opts)
51
+
52
+ st.perform(nil).should be_true
53
+ end
54
+
55
+ it 'should call the method on the object if guard is a symbol' do
56
+ opts = {:from => 'foo', :to => 'bar', :guard => :test}
57
+ st = AASM::SupportingClasses::StateTransition.new(opts)
58
+
59
+ obj = mock('object')
60
+ obj.should_receive(:test)
61
+
62
+ st.perform(obj)
63
+ end
64
+
65
+ it 'should call the method on the object if guard is a string' do
66
+ opts = {:from => 'foo', :to => 'bar', :guard => 'test'}
67
+ st = AASM::SupportingClasses::StateTransition.new(opts)
68
+
69
+ obj = mock('object')
70
+ obj.should_receive(:test)
71
+
72
+ st.perform(obj)
73
+ end
74
+
75
+ it 'should call the proc passing the object if the guard is a proc' do
76
+ opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test}}
77
+ st = AASM::SupportingClasses::StateTransition.new(opts)
78
+
79
+ obj = mock('object')
80
+ obj.should_receive(:test)
81
+
82
+ st.perform(obj)
83
+ end
84
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runcoderun-aasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2.1
4
+ version: 2.0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Barron
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-09 00:00:00 -07:00
12
+ date: 2008-08-13 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,6 +30,7 @@ files:
30
30
  - Rakefile
31
31
  - README.rdoc
32
32
  - TODO
33
+ - aasm.gemspec
33
34
  - lib/aasm.rb
34
35
  - lib/event.rb
35
36
  - lib/persistence/active_record_persistence.rb
@@ -39,6 +40,16 @@ files:
39
40
  - lib/state_transition.rb
40
41
  - lib/version.rb
41
42
  - doc/jamis.rb
43
+ - spec/functional
44
+ - spec/functional/conversation.rb
45
+ - spec/functional/conversation_spec.rb
46
+ - spec/spec_helper.rb
47
+ - spec/unit
48
+ - spec/unit/aasm_spec.rb
49
+ - spec/unit/active_record_persistence_spec.rb
50
+ - spec/unit/event_spec.rb
51
+ - spec/unit/state_spec.rb
52
+ - spec/unit/state_transition_spec.rb
42
53
  has_rdoc: true
43
54
  homepage: http://github.com/rubyist/aasm
44
55
  post_install_message: