2008-01-07 15:07:38 -05:00
|
|
|
require File.join(File.dirname(__FILE__), 'event')
|
2008-02-21 12:32:04 -05:00
|
|
|
require File.join(File.dirname(__FILE__), 'state')
|
2008-02-22 15:46:31 -05:00
|
|
|
require File.join(File.dirname(__FILE__), 'persistence')
|
2008-01-07 15:07:38 -05:00
|
|
|
|
2008-01-07 14:11:38 -05:00
|
|
|
module AASM
|
2008-01-07 15:07:38 -05:00
|
|
|
class InvalidTransition < Exception
|
|
|
|
end
|
|
|
|
|
2008-01-07 14:11:38 -05:00
|
|
|
def self.included(base) #:nodoc:
|
|
|
|
base.extend AASM::ClassMethods
|
2008-02-22 15:46:31 -05:00
|
|
|
AASM::Persistence.set_persistence(base)
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
module ClassMethods
|
2008-02-21 12:59:28 -05:00
|
|
|
def aasm_initial_state(set_state=nil)
|
|
|
|
if set_state
|
|
|
|
aasm_initial_state = set_state
|
|
|
|
else
|
|
|
|
@aasm_initial_state
|
|
|
|
end
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def aasm_initial_state=(state)
|
|
|
|
@aasm_initial_state = state
|
|
|
|
end
|
|
|
|
|
2008-02-21 12:59:28 -05:00
|
|
|
def aasm_state(name, options={})
|
2008-05-31 17:33:45 -04:00
|
|
|
aasm_states << AASM::SupportingClasses::State.new(name, options) unless aasm_states.include?(name)
|
2008-02-21 10:16:08 -05:00
|
|
|
self.aasm_initial_state = name unless self.aasm_initial_state
|
|
|
|
|
2008-01-07 14:11:38 -05:00
|
|
|
define_method("#{name.to_s}?") do
|
2008-01-08 09:39:00 -05:00
|
|
|
aasm_current_state == name
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
end
|
2008-02-21 10:16:08 -05:00
|
|
|
|
2008-05-20 15:27:35 -04:00
|
|
|
def aasm_event(name, options = {}, &block)
|
2008-02-21 12:54:42 -05:00
|
|
|
unless aasm_events.has_key?(name)
|
2008-05-20 15:27:35 -04:00
|
|
|
aasm_events[name] = AASM::SupportingClasses::Event.new(name, options, &block)
|
2008-02-21 12:54:42 -05:00
|
|
|
end
|
2008-02-21 10:16:08 -05:00
|
|
|
|
2008-01-07 14:11:38 -05:00
|
|
|
define_method("#{name.to_s}!") do
|
2008-05-31 17:39:25 -04:00
|
|
|
aasm_fire_event(name, true)
|
2008-04-29 01:27:56 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
define_method("#{name.to_s}") do
|
2008-05-31 17:39:25 -04:00
|
|
|
aasm_fire_event(name, false)
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2008-01-07 15:07:38 -05:00
|
|
|
end
|
|
|
|
|
2008-02-21 12:54:42 -05:00
|
|
|
def aasm_states
|
|
|
|
@aasm_states ||= []
|
|
|
|
end
|
|
|
|
|
2008-01-08 10:03:18 -05:00
|
|
|
def aasm_events
|
2008-01-07 15:07:38 -05:00
|
|
|
@aasm_events ||= {}
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2008-04-14 15:57:34 -04:00
|
|
|
|
|
|
|
def aasm_states_for_select
|
2008-05-31 17:33:45 -04:00
|
|
|
aasm_states.collect { |state| [state.name.to_s.gsub(/_/, ' ').capitalize, state.name.to_s] }
|
2008-04-14 15:57:34 -04:00
|
|
|
end
|
|
|
|
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
2008-02-21 10:16:08 -05:00
|
|
|
# Instance methods
|
2008-01-08 09:39:00 -05:00
|
|
|
def aasm_current_state
|
2008-02-21 11:08:55 -05:00
|
|
|
return @aasm_current_state if @aasm_current_state
|
|
|
|
|
|
|
|
if self.respond_to?(:aasm_read_state) || self.private_methods.include?('aasm_read_state')
|
|
|
|
@aasm_current_state = aasm_read_state
|
|
|
|
end
|
2008-02-22 15:46:31 -05:00
|
|
|
return @aasm_current_state if @aasm_current_state
|
2008-02-21 11:08:55 -05:00
|
|
|
self.class.aasm_initial_state
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2008-01-08 09:39:00 -05:00
|
|
|
|
2008-02-28 08:33:40 -05:00
|
|
|
def aasm_events_for_current_state
|
|
|
|
aasm_events_for_state(aasm_current_state)
|
|
|
|
end
|
|
|
|
|
|
|
|
def aasm_events_for_state(state)
|
|
|
|
events = self.class.aasm_events.values.select {|event| event.transitions_from_state?(state) }
|
|
|
|
events.map {|event| event.name}
|
|
|
|
end
|
|
|
|
|
2008-01-08 09:39:00 -05:00
|
|
|
private
|
2008-04-29 01:27:56 -04:00
|
|
|
def aasm_current_state_with_persistence=(state)
|
2008-02-21 11:08:55 -05:00
|
|
|
if self.respond_to?(:aasm_write_state) || self.private_methods.include?('aasm_write_state')
|
2008-02-21 11:15:40 -05:00
|
|
|
aasm_write_state(state)
|
2008-01-08 09:39:00 -05:00
|
|
|
end
|
2008-04-29 01:27:56 -04:00
|
|
|
self.aasm_current_state = state
|
2008-01-08 09:39:00 -05:00
|
|
|
end
|
2008-04-29 01:27:56 -04:00
|
|
|
|
|
|
|
def aasm_current_state=(state)
|
|
|
|
if self.respond_to?(:aasm_write_state_without_persistence) || self.private_methods.include?('aasm_write_state_without_persistence')
|
|
|
|
aasm_write_state_without_persistence(state)
|
|
|
|
end
|
|
|
|
@aasm_current_state = state
|
|
|
|
end
|
|
|
|
|
2008-05-31 18:08:12 -04:00
|
|
|
def aasm_state_object_for_state(name)
|
|
|
|
self.class.aasm_states.find {|s| s == name}
|
|
|
|
end
|
|
|
|
|
2008-05-31 17:39:25 -04:00
|
|
|
def aasm_fire_event(name, persist)
|
2008-05-31 18:08:12 -04:00
|
|
|
aasm_state_object_for_state(aasm_current_state).call_action(:exit, self)
|
|
|
|
|
2008-05-31 17:39:25 -04:00
|
|
|
new_state = self.class.aasm_events[name].fire(self)
|
2008-05-31 18:08:12 -04:00
|
|
|
|
2008-05-31 17:39:25 -04:00
|
|
|
unless new_state.nil?
|
2008-05-31 18:08:12 -04:00
|
|
|
aasm_state_object_for_state(new_state).call_action(:enter, self)
|
|
|
|
|
2008-05-31 17:39:25 -04:00
|
|
|
if self.respond_to?(:aasm_event_fired)
|
|
|
|
self.aasm_event_fired(self.aasm_current_state, new_state)
|
|
|
|
end
|
|
|
|
|
|
|
|
if persist
|
|
|
|
self.aasm_current_state_with_persistence = new_state
|
|
|
|
self.send(self.class.aasm_events[name].success) if self.class.aasm_events[name].success
|
|
|
|
else
|
|
|
|
self.aasm_current_state = new_state
|
|
|
|
end
|
|
|
|
|
|
|
|
true
|
|
|
|
else
|
|
|
|
if self.respond_to?(:aasm_event_failed)
|
|
|
|
self.aasm_event_failed(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|