aasm 3.0.16 → 3.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +2 -1
- data/API +34 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +1 -1
- data/HOWTO +12 -0
- data/README.md +57 -4
- data/aasm.gemspec +2 -0
- data/lib/aasm.rb +5 -4
- data/lib/aasm/aasm.rb +50 -75
- data/lib/aasm/base.rb +22 -18
- data/lib/aasm/event.rb +130 -0
- data/lib/aasm/instance_base.rb +87 -0
- data/lib/aasm/localizer.rb +54 -0
- data/lib/aasm/persistence.rb +22 -14
- data/lib/aasm/persistence/active_record_persistence.rb +38 -69
- data/lib/aasm/persistence/base.rb +42 -2
- data/lib/aasm/persistence/mongoid_persistence.rb +33 -64
- data/lib/aasm/state.rb +78 -0
- data/lib/aasm/state_machine.rb +2 -2
- data/lib/aasm/transition.rb +49 -0
- data/lib/aasm/version.rb +1 -1
- data/spec/models/active_record/api.rb +75 -0
- data/spec/models/auth_machine.rb +1 -1
- data/spec/models/bar.rb +15 -0
- data/spec/models/foo.rb +34 -0
- data/spec/models/mongoid/simple_mongoid.rb +10 -0
- data/spec/models/mongoid/{mongoid_models.rb → simple_new_dsl_mongoid.rb} +1 -12
- data/spec/models/persistence.rb +2 -1
- data/spec/models/this_name_better_not_be_in_use.rb +11 -0
- data/spec/schema.rb +1 -1
- data/spec/spec_helper.rb +8 -1
- data/spec/unit/api_spec.rb +72 -0
- data/spec/unit/callbacks_spec.rb +2 -2
- data/spec/unit/event_spec.rb +269 -0
- data/spec/unit/inspection_spec.rb +43 -5
- data/spec/unit/{supporting_classes/localizer_spec.rb → localizer_spec.rb} +2 -2
- data/spec/unit/memory_leak_spec.rb +12 -12
- data/spec/unit/persistence/active_record_persistence_spec.rb +0 -40
- data/spec/unit/persistence/mongoid_persistance_spec.rb +3 -2
- data/spec/unit/simple_example_spec.rb +6 -0
- data/spec/unit/{supporting_classes/state_spec.rb → state_spec.rb} +2 -2
- data/spec/unit/{supporting_classes/state_transition_spec.rb → transition_spec.rb} +18 -18
- metadata +127 -38
- data/lib/aasm/persistence/read_state.rb +0 -40
- data/lib/aasm/supporting_classes/event.rb +0 -146
- data/lib/aasm/supporting_classes/localizer.rb +0 -56
- data/lib/aasm/supporting_classes/state.rb +0 -80
- data/lib/aasm/supporting_classes/state_transition.rb +0 -51
- data/spec/spec_helpers/models_spec_helper.rb +0 -64
- data/spec/unit/supporting_classes/event_spec.rb +0 -203
@@ -1,40 +0,0 @@
|
|
1
|
-
module AASM
|
2
|
-
module Persistence
|
3
|
-
module ReadState
|
4
|
-
|
5
|
-
# Returns the value of the aasm_column - called from <tt>aasm_current_state</tt>
|
6
|
-
#
|
7
|
-
# If it's a new record, and the aasm state column is blank it returns the initial state
|
8
|
-
# (example provided here for ActiveRecord, but it's true for Mongoid as well):
|
9
|
-
#
|
10
|
-
# class Foo < ActiveRecord::Base
|
11
|
-
# include AASM
|
12
|
-
# aasm_column :status
|
13
|
-
# aasm_state :opened
|
14
|
-
# aasm_state :closed
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# foo = Foo.new
|
18
|
-
# foo.current_state # => :opened
|
19
|
-
# foo.close
|
20
|
-
# foo.current_state # => :closed
|
21
|
-
#
|
22
|
-
# foo = Foo.find(1)
|
23
|
-
# foo.current_state # => :opened
|
24
|
-
# foo.aasm_state = nil
|
25
|
-
# foo.current_state # => nil
|
26
|
-
#
|
27
|
-
# NOTE: intended to be called from an event
|
28
|
-
#
|
29
|
-
# This allows for nil aasm states - be sure to add validation to your model
|
30
|
-
def aasm_read_state
|
31
|
-
if new_record?
|
32
|
-
send(self.class.aasm_column).blank? ? aasm_determine_state_name(self.class.aasm_initial_state) : send(self.class.aasm_column).to_sym
|
33
|
-
else
|
34
|
-
send(self.class.aasm_column).nil? ? nil : send(self.class.aasm_column).to_sym
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end # ReadState
|
39
|
-
end # Persistence
|
40
|
-
end # AASM
|
@@ -1,146 +0,0 @@
|
|
1
|
-
module AASM
|
2
|
-
module SupportingClasses
|
3
|
-
class Event
|
4
|
-
attr_reader :name, :success, :options
|
5
|
-
|
6
|
-
def initialize(name, options = {}, &block)
|
7
|
-
@name = name
|
8
|
-
@transitions = []
|
9
|
-
update(options, &block)
|
10
|
-
end
|
11
|
-
|
12
|
-
# a neutered version of fire - it doesn't actually fire the event, it just
|
13
|
-
# executes the transition guards to determine if a transition is even
|
14
|
-
# an option given current conditions.
|
15
|
-
def may_fire?(obj, to_state=nil, *args)
|
16
|
-
_fire(obj, true, to_state, *args) # true indicates test firing
|
17
|
-
end
|
18
|
-
|
19
|
-
def fire(obj, to_state=nil, *args)
|
20
|
-
_fire(obj, false, to_state, *args) # false indicates this is not a test (fire!)
|
21
|
-
end
|
22
|
-
|
23
|
-
def transitions_from_state?(state)
|
24
|
-
transitions_from_state(state).any?
|
25
|
-
end
|
26
|
-
|
27
|
-
def transitions_from_state(state)
|
28
|
-
@transitions.select { |t| t.from == state }
|
29
|
-
end
|
30
|
-
|
31
|
-
def transitions_to_state?(state)
|
32
|
-
transitions_to_state(state).any?
|
33
|
-
end
|
34
|
-
|
35
|
-
def transitions_to_state(state)
|
36
|
-
@transitions.select { |t| t.to == state }
|
37
|
-
end
|
38
|
-
|
39
|
-
def all_transitions
|
40
|
-
@transitions
|
41
|
-
end
|
42
|
-
|
43
|
-
def fire_callbacks(action, record)
|
44
|
-
action = @options[action]
|
45
|
-
action.is_a?(Array) ?
|
46
|
-
action.each {|a| _fire_callbacks(a, record)} :
|
47
|
-
_fire_callbacks(action, record)
|
48
|
-
end
|
49
|
-
|
50
|
-
def ==(event)
|
51
|
-
if event.is_a? Symbol
|
52
|
-
name == event
|
53
|
-
else
|
54
|
-
name == event.name
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def execute_success_callback(obj, success = nil)
|
59
|
-
callback = success || @success
|
60
|
-
case(callback)
|
61
|
-
when String, Symbol
|
62
|
-
obj.send(callback)
|
63
|
-
when Proc
|
64
|
-
callback.call(obj)
|
65
|
-
when Array
|
66
|
-
callback.each{|meth|self.execute_success_callback(obj, meth)}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def execute_error_callback(obj, error, error_callback=nil)
|
71
|
-
callback = error_callback || @error
|
72
|
-
raise error unless callback
|
73
|
-
case(callback)
|
74
|
-
when String, Symbol
|
75
|
-
raise NoMethodError unless obj.respond_to?(callback.to_sym)
|
76
|
-
obj.send(callback, error)
|
77
|
-
when Proc
|
78
|
-
callback.call(obj, error)
|
79
|
-
when Array
|
80
|
-
callback.each{|meth|self.execute_error_callback(obj, error, meth)}
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def update(options = {}, &block)
|
87
|
-
if options.key?(:success) then
|
88
|
-
@success = options[:success]
|
89
|
-
end
|
90
|
-
if options.key?(:error) then
|
91
|
-
@error = options[:error]
|
92
|
-
end
|
93
|
-
if block then
|
94
|
-
instance_eval(&block)
|
95
|
-
end
|
96
|
-
@options = options
|
97
|
-
self
|
98
|
-
end
|
99
|
-
|
100
|
-
# Execute if test? == false, otherwise return true/false depending on whether it would fire
|
101
|
-
def _fire(obj, test, to_state=nil, *args)
|
102
|
-
if @transitions.map(&:from).any?
|
103
|
-
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
104
|
-
return nil if transitions.size == 0
|
105
|
-
else
|
106
|
-
transitions = @transitions
|
107
|
-
end
|
108
|
-
|
109
|
-
result = test ? false : nil
|
110
|
-
transitions.each do |transition|
|
111
|
-
next if to_state and !Array(transition.to).include?(to_state)
|
112
|
-
if transition.perform(obj, *args)
|
113
|
-
if test
|
114
|
-
result = true
|
115
|
-
else
|
116
|
-
result = to_state || Array(transition.to).first
|
117
|
-
transition.execute(obj, *args)
|
118
|
-
end
|
119
|
-
|
120
|
-
break
|
121
|
-
end
|
122
|
-
end
|
123
|
-
result
|
124
|
-
end
|
125
|
-
|
126
|
-
def _fire_callbacks(action, record)
|
127
|
-
case action
|
128
|
-
when Symbol, String
|
129
|
-
record.send(action)
|
130
|
-
when Proc
|
131
|
-
action.call(record)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def transitions(trans_opts)
|
136
|
-
# Create a separate transition for each from state to the given state
|
137
|
-
Array(trans_opts[:from]).each do |s|
|
138
|
-
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym}))
|
139
|
-
end
|
140
|
-
# Create a transition if to is specified without from (transitions from ANY state)
|
141
|
-
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts) if @transitions.empty? && trans_opts[:to]
|
142
|
-
end
|
143
|
-
|
144
|
-
end
|
145
|
-
end # SupportingClasses
|
146
|
-
end # AASM
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module AASM
|
2
|
-
module SupportingClasses
|
3
|
-
class Localizer
|
4
|
-
def human_event_name(klass, event)
|
5
|
-
checklist = ancestors_list(klass).inject([]) do |list, ancestor|
|
6
|
-
list << :"#{i18n_scope(klass)}.events.#{i18n_klass(ancestor)}.#{event}"
|
7
|
-
list
|
8
|
-
end
|
9
|
-
translate_queue(checklist) || I18n.translate(checklist.shift, :default => event.to_s.humanize)
|
10
|
-
end
|
11
|
-
|
12
|
-
def human_state_name(klass, state)
|
13
|
-
checklist = ancestors_list(klass).inject([]) do |list, ancestor|
|
14
|
-
list << item_for(klass, state, ancestor)
|
15
|
-
list << item_for(klass, state, ancestor, :old_style => true)
|
16
|
-
list
|
17
|
-
end
|
18
|
-
translate_queue(checklist) || I18n.translate(checklist.shift, :default => state.to_s.humanize)
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def item_for(klass, state, ancestor, options={})
|
24
|
-
separator = options[:old_style] ? '.' : '/'
|
25
|
-
:"#{i18n_scope(klass)}.attributes.#{i18n_klass(ancestor)}.#{klass.aasm_column}#{separator}#{state}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def translate_queue(checklist)
|
29
|
-
(0...(checklist.size-1)).each do |i|
|
30
|
-
begin
|
31
|
-
return I18n.translate(checklist.shift, :raise => true)
|
32
|
-
rescue I18n::MissingTranslationData
|
33
|
-
# that's okay
|
34
|
-
end
|
35
|
-
end
|
36
|
-
nil
|
37
|
-
end
|
38
|
-
|
39
|
-
# added for rails 2.x compatibility
|
40
|
-
def i18n_scope(klass)
|
41
|
-
klass.respond_to?(:i18n_scope) ? klass.i18n_scope : :activerecord
|
42
|
-
end
|
43
|
-
|
44
|
-
# added for rails < 3.0.3 compatibility
|
45
|
-
def i18n_klass(klass)
|
46
|
-
klass.model_name.respond_to?(:i18n_key) ? klass.model_name.i18n_key : klass.name.underscore
|
47
|
-
end
|
48
|
-
|
49
|
-
def ancestors_list(klass)
|
50
|
-
klass.ancestors.select do |ancestor|
|
51
|
-
ancestor.respond_to?(:model_name) unless ancestor == ActiveRecord::Base
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end # SupportingClasses
|
56
|
-
end # AASM
|
@@ -1,80 +0,0 @@
|
|
1
|
-
module AASM
|
2
|
-
module SupportingClasses
|
3
|
-
class State
|
4
|
-
attr_reader :name, :options
|
5
|
-
|
6
|
-
def initialize(name, clazz, options={})
|
7
|
-
@name = name
|
8
|
-
@clazz = clazz
|
9
|
-
update(options)
|
10
|
-
end
|
11
|
-
|
12
|
-
def ==(state)
|
13
|
-
if state.is_a? Symbol
|
14
|
-
name == state
|
15
|
-
else
|
16
|
-
name == state.name
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def <=>(state)
|
21
|
-
if state.is_a? Symbol
|
22
|
-
name <=> state
|
23
|
-
else
|
24
|
-
name <=> state.name
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_s
|
29
|
-
name.to_s
|
30
|
-
end
|
31
|
-
|
32
|
-
def fire_callbacks(action, record)
|
33
|
-
action = @options[action]
|
34
|
-
catch :halt_aasm_chain do
|
35
|
-
action.is_a?(Array) ?
|
36
|
-
action.each {|a| _fire_callbacks(a, record)} :
|
37
|
-
_fire_callbacks(action, record)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def display_name
|
42
|
-
@display_name ||= begin
|
43
|
-
if Module.const_defined?(:I18n)
|
44
|
-
localized_name
|
45
|
-
else
|
46
|
-
name.to_s.gsub(/_/, ' ').capitalize
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def localized_name
|
52
|
-
AASM::SupportingClasses::Localizer.new.human_state_name(@clazz, self)
|
53
|
-
end
|
54
|
-
|
55
|
-
def for_select
|
56
|
-
[display_name, name.to_s]
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def update(options = {})
|
62
|
-
if options.key?(:display) then
|
63
|
-
@display_name = options.delete(:display)
|
64
|
-
end
|
65
|
-
@options = options
|
66
|
-
self
|
67
|
-
end
|
68
|
-
|
69
|
-
def _fire_callbacks(action, record)
|
70
|
-
case action
|
71
|
-
when Symbol, String
|
72
|
-
record.send(action)
|
73
|
-
when Proc
|
74
|
-
action.call(record)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end # SupportingClasses
|
80
|
-
end # AASM
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module AASM
|
2
|
-
module SupportingClasses
|
3
|
-
class StateTransition
|
4
|
-
attr_reader :from, :to, :opts
|
5
|
-
alias_method :options, :opts
|
6
|
-
|
7
|
-
def initialize(opts)
|
8
|
-
@from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition]
|
9
|
-
@opts = opts
|
10
|
-
end
|
11
|
-
|
12
|
-
# TODO: should be named allowed? or similar
|
13
|
-
def perform(obj, *args)
|
14
|
-
case @guard
|
15
|
-
when Symbol, String
|
16
|
-
obj.send(@guard, *args)
|
17
|
-
when Proc
|
18
|
-
@guard.call(obj, *args)
|
19
|
-
else
|
20
|
-
true
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def execute(obj, *args)
|
25
|
-
@on_transition.is_a?(Array) ?
|
26
|
-
@on_transition.each {|ot| _execute(obj, ot, *args)} :
|
27
|
-
_execute(obj, @on_transition, *args)
|
28
|
-
end
|
29
|
-
|
30
|
-
def ==(obj)
|
31
|
-
@from == obj.from && @to == obj.to
|
32
|
-
end
|
33
|
-
|
34
|
-
def from?(value)
|
35
|
-
@from == value
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def _execute(obj, on_transition, *args)
|
41
|
-
case on_transition
|
42
|
-
when Proc
|
43
|
-
on_transition.arity == 0 ? on_transition.call : on_transition.call(obj, *args)
|
44
|
-
when Symbol, String
|
45
|
-
obj.send(:method, on_transition.to_sym).arity == 0 ? obj.send(on_transition) : obj.send(on_transition, *args)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
end # SupportingClasses
|
51
|
-
end # AASM
|
@@ -1,64 +0,0 @@
|
|
1
|
-
Dir[File.dirname(__FILE__) + "/../models/*.rb"].sort.each { |f| require File.expand_path(f) }
|
2
|
-
|
3
|
-
class Foo
|
4
|
-
include AASM
|
5
|
-
aasm do
|
6
|
-
state :open, :initial => true, :exit => :exit
|
7
|
-
state :closed, :enter => :enter
|
8
|
-
|
9
|
-
event :close, :success => :success_callback do
|
10
|
-
transitions :to => :closed, :from => [:open]
|
11
|
-
end
|
12
|
-
|
13
|
-
event :null do
|
14
|
-
transitions :to => :closed, :from => [:open], :guard => :always_false
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def always_false
|
19
|
-
false
|
20
|
-
end
|
21
|
-
|
22
|
-
def success_callback
|
23
|
-
end
|
24
|
-
|
25
|
-
def enter
|
26
|
-
end
|
27
|
-
def exit
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class FooTwo < Foo
|
32
|
-
include AASM
|
33
|
-
aasm do
|
34
|
-
state :foo
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class Bar
|
39
|
-
include AASM
|
40
|
-
|
41
|
-
aasm do
|
42
|
-
state :read
|
43
|
-
state :ended
|
44
|
-
|
45
|
-
event :foo do
|
46
|
-
transitions :to => :ended, :from => [:read]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class Baz < Bar
|
52
|
-
end
|
53
|
-
|
54
|
-
class ThisNameBetterNotBeInUse
|
55
|
-
include AASM
|
56
|
-
|
57
|
-
aasm do
|
58
|
-
state :initial
|
59
|
-
state :symbol
|
60
|
-
state :string
|
61
|
-
state :array
|
62
|
-
state :proc
|
63
|
-
end
|
64
|
-
end
|
@@ -1,203 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'adding an event' do
|
4
|
-
let(:event) do
|
5
|
-
AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
|
6
|
-
transitions :to => :closed, :from => [:open, :received]
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'should set the name' do
|
11
|
-
event.name.should == :close_order
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'should set the success callback' do
|
15
|
-
event.success.should == :success_callback
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should create transitions' do
|
19
|
-
transitions = event.all_transitions
|
20
|
-
transitions[0].from.should == :open
|
21
|
-
transitions[0].to.should == :closed
|
22
|
-
transitions[1].from.should == :received
|
23
|
-
transitions[1].to.should == :closed
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'transition inspection' do
|
28
|
-
let(:event) do
|
29
|
-
AASM::SupportingClasses::Event.new(:run) do
|
30
|
-
transitions :to => :running, :from => :sleeping
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should support inspecting transitions from other states' do
|
35
|
-
event.transitions_from_state(:sleeping).map(&:to).should == [:running]
|
36
|
-
event.transitions_from_state?(:sleeping).should be_true
|
37
|
-
|
38
|
-
event.transitions_from_state(:cleaning).map(&:to).should == []
|
39
|
-
event.transitions_from_state?(:cleaning).should be_false
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should support inspecting transitions to other states' do
|
43
|
-
event.transitions_to_state(:running).map(&:from).should == [:sleeping]
|
44
|
-
event.transitions_to_state?(:running).should be_true
|
45
|
-
|
46
|
-
event.transitions_to_state(:cleaning).map(&:to).should == []
|
47
|
-
event.transitions_to_state?(:cleaning).should be_false
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'firing an event' do
|
52
|
-
it 'should return nil if the transitions are empty' do
|
53
|
-
obj = mock('object')
|
54
|
-
obj.stub!(:aasm_current_state)
|
55
|
-
|
56
|
-
event = AASM::SupportingClasses::Event.new(:event)
|
57
|
-
event.fire(obj).should be_nil
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'should return the state of the first matching transition it finds' do
|
61
|
-
event = AASM::SupportingClasses::Event.new(:event) do
|
62
|
-
transitions :to => :closed, :from => [:open, :received]
|
63
|
-
end
|
64
|
-
|
65
|
-
obj = mock('object')
|
66
|
-
obj.stub!(:aasm_current_state).and_return(:open)
|
67
|
-
|
68
|
-
event.fire(obj).should == :closed
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should call the guard with the params passed in' do
|
72
|
-
event = AASM::SupportingClasses::Event.new(:event) do
|
73
|
-
transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
|
74
|
-
end
|
75
|
-
|
76
|
-
obj = mock('object')
|
77
|
-
obj.stub!(:aasm_current_state).and_return(:open)
|
78
|
-
obj.should_receive(:guard_fn).with('arg1', 'arg2').and_return(true)
|
79
|
-
|
80
|
-
event.fire(obj, nil, 'arg1', 'arg2').should == :closed
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
describe 'executing the success callback' do
|
86
|
-
|
87
|
-
it "should send the success callback if it's a symbol" do
|
88
|
-
ThisNameBetterNotBeInUse.instance_eval {
|
89
|
-
aasm_event :with_symbol, :success => :symbol_success_callback do
|
90
|
-
transitions :to => :symbol, :from => [:initial]
|
91
|
-
end
|
92
|
-
}
|
93
|
-
|
94
|
-
model = ThisNameBetterNotBeInUse.new
|
95
|
-
model.should_receive(:symbol_success_callback)
|
96
|
-
model.with_symbol!
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should send the success callback if it's a string" do
|
100
|
-
ThisNameBetterNotBeInUse.instance_eval {
|
101
|
-
aasm_event :with_string, :success => 'string_success_callback' do
|
102
|
-
transitions :to => :string, :from => [:initial]
|
103
|
-
end
|
104
|
-
}
|
105
|
-
|
106
|
-
model = ThisNameBetterNotBeInUse.new
|
107
|
-
model.should_receive(:string_success_callback)
|
108
|
-
model.with_string!
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should call each success callback if passed an array of strings and/or symbols" do
|
112
|
-
ThisNameBetterNotBeInUse.instance_eval {
|
113
|
-
aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do
|
114
|
-
transitions :to => :array, :from => [:initial]
|
115
|
-
end
|
116
|
-
}
|
117
|
-
|
118
|
-
model = ThisNameBetterNotBeInUse.new
|
119
|
-
model.should_receive(:success_callback1)
|
120
|
-
model.should_receive(:success_callback2)
|
121
|
-
model.with_array!
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should call each success callback if passed an array of strings and/or symbols and/or procs" do
|
125
|
-
ThisNameBetterNotBeInUse.instance_eval {
|
126
|
-
aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { |obj| obj.proc_success_callback }] do
|
127
|
-
transitions :to => :array, :from => [:initial]
|
128
|
-
end
|
129
|
-
}
|
130
|
-
|
131
|
-
model = ThisNameBetterNotBeInUse.new
|
132
|
-
model.should_receive(:success_callback1)
|
133
|
-
model.should_receive(:success_callback2)
|
134
|
-
model.should_receive(:proc_success_callback)
|
135
|
-
model.with_array_including_procs!
|
136
|
-
end
|
137
|
-
|
138
|
-
it "should call the success callback if it's a proc" do
|
139
|
-
ThisNameBetterNotBeInUse.instance_eval {
|
140
|
-
aasm_event :with_proc, :success => lambda { |obj| obj.proc_success_callback } do
|
141
|
-
transitions :to => :proc, :from => [:initial]
|
142
|
-
end
|
143
|
-
}
|
144
|
-
|
145
|
-
model = ThisNameBetterNotBeInUse.new
|
146
|
-
model.should_receive(:proc_success_callback)
|
147
|
-
model.with_proc!
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
describe 'parametrised events' do
|
152
|
-
let(:pe) {ParametrisedEvent.new}
|
153
|
-
|
154
|
-
it 'should transition to specified next state (sleeping to showering)' do
|
155
|
-
pe.wakeup!(:showering)
|
156
|
-
pe.aasm_current_state.should == :showering
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'should transition to specified next state (sleeping to working)' do
|
160
|
-
pe.wakeup!(:working)
|
161
|
-
pe.aasm_current_state.should == :working
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'should transition to default (first or showering) state' do
|
165
|
-
pe.wakeup!
|
166
|
-
pe.aasm_current_state.should == :showering
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'should transition to default state when on_transition invoked' do
|
170
|
-
pe.dress!(nil, 'purple', 'dressy')
|
171
|
-
pe.aasm_current_state.should == :working
|
172
|
-
end
|
173
|
-
|
174
|
-
it 'should call on_transition method with args' do
|
175
|
-
pe.wakeup!(:showering)
|
176
|
-
pe.should_receive(:wear_clothes).with('blue', 'jeans')
|
177
|
-
pe.dress!(:working, 'blue', 'jeans')
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'should call on_transition proc' do
|
181
|
-
pe.wakeup!(:showering)
|
182
|
-
pe.should_receive(:wear_clothes).with('purple', 'slacks')
|
183
|
-
pe.dress!(:dating, 'purple', 'slacks')
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'should call on_transition with an array of methods' do
|
187
|
-
pe.wakeup!(:showering)
|
188
|
-
pe.should_receive(:condition_hair)
|
189
|
-
pe.should_receive(:fix_hair)
|
190
|
-
pe.dress!(:prettying_up)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
describe 'event firing without persistence' do
|
195
|
-
it 'should attempt to persist if aasm_write_state is defined' do
|
196
|
-
foo = Foo.new
|
197
|
-
def foo.aasm_write_state; end
|
198
|
-
foo.should be_open
|
199
|
-
|
200
|
-
foo.should_receive(:aasm_write_state_without_persistence)
|
201
|
-
foo.close
|
202
|
-
end
|
203
|
-
end
|