Skip to content

Instantly share code, notes, and snippets.

@godfat
Created April 13, 2010 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save godfat/364446 to your computer and use it in GitHub Desktop.
Save godfat/364446 to your computer and use it in GitHub Desktop.
require 'aasm'
class Cat
include AASM
attr_writer :stomach
# how would you like to read the state?
# database? memcache?
def aasm_read_state
puts " read: Examining stomach... #{@stomach || 'nothing'}!"
@stomach || self.class.aasm_initial_state
end
# how would you like to write the state?
# database? memcache? only save it when state changed
def aasm_write_state_without_persistence food
puts "write: Eating... #{food}!"
@stomach = food if food != @stomach
end
aasm_initial_state :nothing
# state exit callback and state enter callback
aasm_state :nothing, :exit => :ate
aasm_state :fish, :enter => :found
# guard if this transition could process
aasm_event :eat do
transitions :from => [:nothing],
:to => :fish,
:guard => :fish_left?
end
# state transition callback
aasm_event :digest do
transitions :from => [:fish, :nothing],
:to => :nothing,
:on_transition => :digesting
end
def ate
puts " exit: Ate #{aasm_current_state}..."
end
# don't do this, state callback would be called
# when reading from database/memcache to initialize
# so this would yield unexpected result.
# state callback should have no side-effect at all.
# put side-effect only in transition callback
def found
puts "enter: Found #{@fish_amount} fish left!"
@fish_amount -= 1
end
def fish_left?
puts "guard: fish left: #{@fish_amount ||= 2}"
@fish_amount > 0
end
def digesting
puts "on_transition: Digesting #{aasm_current_state}..."
end
def silence_exception e
puts "ate exception #{e.inspect}"
end
aasm_events.each{ |(name, event)|
event.update(event.options.merge(:error => :silence_exception))
}
# pool man's state pattern
def say
send("say_#{aasm_current_state}")
end
def say_nothing
puts ' say: I have nothing...'
end
def say_fish
puts ' say: I have fish!'
end
end
def test c = Cat.new
puts '-'*30
puts 'c.digest'; c.digest; puts
puts 'c.eat' ; c.eat ; puts
puts 'c.digest'; c.digest; puts
puts 'c.digest'; c.digest; puts
puts 'c.eat' ; c.eat ; puts
puts 'c.say' ; c.say ; puts
c.send(:instance_variable_set, '@aasm_current_state', nil)
c
end
c = test(test)
c.send(:aasm_current_state=, :fish)
c.eat
__END__
~> ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin10]
~> gem list aasm
*** LOCAL GEMS ***
aasm (2.1.5)
~> ruby cat.rb
------------------------------
c.digest
read: Examining stomach... nothing!
exit: Ate nothing...
on_transition: Digesting nothing...
write: Eating... nothing!
c.eat
exit: Ate nothing...
guard: fish left: 2
enter: Found 2 fish left!
write: Eating... fish!
c.digest
on_transition: Digesting fish...
write: Eating... nothing!
c.digest
exit: Ate nothing...
on_transition: Digesting nothing...
write: Eating... nothing!
c.eat
exit: Ate nothing...
guard: fish left: 1
enter: Found 1 fish left!
write: Eating... fish!
c.say
say: I have fish!
------------------------------
c.digest
read: Examining stomach... fish!
on_transition: Digesting fish...
write: Eating... nothing!
c.eat
exit: Ate nothing...
guard: fish left: 0
c.digest
exit: Ate nothing...
on_transition: Digesting nothing...
write: Eating... nothing!
c.digest
exit: Ate nothing...
on_transition: Digesting nothing...
write: Eating... nothing!
c.eat
exit: Ate nothing...
guard: fish left: 0
c.say
say: I have nothing...
write: Eating... fish!
ate exception #<AASM::InvalidTransition: Event 'eat' cannot transition from 'fish'>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment