Added initial state Proc support.

Added more complex example to README
This commit is contained in:
Nathaniel Bibler 2009-02-26 12:06:43 -05:00
parent baceb4b53e
commit f87565f2e4
5 changed files with 84 additions and 2 deletions

View File

@ -57,6 +57,38 @@ Here's a quick example highlighting some of the features.
end
end
== A Slightly More Complex Example
This example uses a few of the more complex features available.
class Relationship
include AASM
aasm_initial_state Proc.new { |relationship| relationship.strictly_for_fun? ? :intimate : :dating }
aasm_state :dating, :enter => :make_happy, :exit => :make_depressed
aasm_state :intimate, :enter => :make_very_happy, :exit => :never_speak_again
aasm_state :married, :enter => :give_up_intimacy, :exit => :buy_exotic_car_and_wear_a_combover
aasm_event :get_intimate do
transitions :to => :intimate, :from => [:dating], :guard => :drunk?
end
aasm_event :get_married do
transitions :to => :married, :from => [:dating, :intimate], :guard => :willing_to_give_up_manhood?
end
def strictly_for_fun?; end
def drunk?; end
def willing_to_give_up_manhood?; end
def make_happy; end
def make_depressed; end
def make_very_happy; end
def never_speak_again; end
def give_up_intimacy; end
def buy_exotic_car_and_wear_a_combover; end
end
= Other Stuff
Author:: Scott Barron <scott at elitists dot net>

View File

@ -89,7 +89,7 @@ module AASM
@aasm_current_state = aasm_read_state
end
return @aasm_current_state if @aasm_current_state
self.class.aasm_initial_state
aasm_determine_state_name(self.class.aasm_initial_state)
end
def aasm_events_for_current_state
@ -118,6 +118,17 @@ module AASM
end
@aasm_current_state = state
end
def aasm_determine_state_name(state)
case state
when Symbol, String
state
when Proc
state.call(self)
else
raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc."
end
end
def aasm_state_object_for_state(name)
obj = self.class.aasm_states.find {|s| s == name}

View File

@ -228,7 +228,7 @@ module AASM
# This allows for nil aasm states - be sure to add validation to your model
def aasm_read_state
if new_record?
send(self.class.aasm_column).blank? ? self.class.aasm_initial_state : send(self.class.aasm_column).to_sym
send(self.class.aasm_column).blank? ? aasm_determine_state_name(self.class.aasm_initial_state) : send(self.class.aasm_column).to_sym
else
send(self.class.aasm_column).nil? ? nil : send(self.class.aasm_column).to_sym
end

View File

@ -41,6 +41,17 @@ end
class Baz < Bar
end
class Banker
include AASM
aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
aasm_state :retired
aasm_state :selling_bad_mortgages
RICH = 1_000_000
attr_accessor :balance
def initialize(balance = 0); self.balance = balance; end
def rich?; self.balance >= RICH; end
end
describe AASM, '- class level definitions' do
it 'should define a class level aasm_initial_state() method on its including class' do
@ -130,6 +141,11 @@ describe AASM, '- initial states' do
it 'should use the first state defined if no initial state is given' do
@bar.aasm_current_state.should == :read
end
it 'should determine initial state from the Proc results' do
Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages
Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired
end
end
describe AASM, '- event firing with persistence' do

View File

@ -50,6 +50,14 @@ begin
class Beaver < June
end
class Thief < ActiveRecord::Base
include AASM
aasm_initial_state Proc.new { |thief| thief.skilled ? :rich : :jailed }
aasm_state :rich
aasm_state :jailed
attr_accessor :skilled, :aasm_state
end
describe "aasm model", :shared => true do
it "should include AASM::Persistence::ActiveRecordPersistence" do
@ -219,6 +227,21 @@ begin
end
end
end
describe 'Thieves' do
before(:each) do
connection = mock(Connection, :columns => [])
Thief.stub!(:connection).and_return(connection)
end
it 'should be rich if they\'re skilled' do
Thief.new(:skilled => true).aasm_current_state.should == :rich
end
it 'should be jailed if they\'re unskilled' do
Thief.new(:skilled => false).aasm_current_state.should == :jailed
end
end
# TODO: figure out how to test ActiveRecord reload! without a database