aasm 3.0.16 → 3.0.17
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/.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
|