mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Merge commit 'nbibler/dynamic_initial_state'
This commit is contained in:
commit
15915ad6e7
5 changed files with 84 additions and 2 deletions
32
README.rdoc
32
README.rdoc
|
@ -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>
|
||||
|
|
13
lib/aasm.rb
13
lib/aasm.rb
|
@ -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}
|
||||
|
|
|
@ -230,7 +230,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue