Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2084726
  • 博文数量: 414
  • 博客积分: 10312
  • 博客等级: 上将
  • 技术积分: 4921
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-31 01:49
文章分类

全部博文(414)

文章存档

2011年(1)

2010年(29)

2009年(82)

2008年(301)

2007年(1)

分类:

2008-07-19 13:02:00

I’ve been noticing a pattern in several of my projects where I’m having a model object keep track of its state. Sometimes it’s a simple boolean flag, and this presents little problem. Other times, it gets more complex. In a current project, things started out simply. Then the model evolved and finally I realized that I was using three boolean variables to keep the state. To make matters worse, these three flags were being distilled into one state. Needless to say, this collapsed under its own tremendous weight fairly quickly.

So I stood at my newly hung whiteboard and thought and thought. I realized that this object was not just in a state, but moving from state to state, in a well defined series of steps, throughout its lifetime. I do believe this is what them academicals calls a “finite automaton” or “state machine” for those of us who doodled or slept during class. I drew some circles and lines (I have 4 colors) and concluded that yes, this was a fine idea, I would make some coffee and write this immediately.

I’ve been hacking at it here and there for a few days, incorporating it into some projects. It’s working well. Today I’ve reached what I’ve tagged release 2.0 of the Acts As State Machine plugin. I’m still polishing the documentation, but you can find some quick . You can get the code with svn from . You’ll probably have to log in as anonymous/anonymous because I’m too dumb to figure out how to make TxD serve that up without authentication.

Give it a try if you like, send feedback if it pleases you. You’ll be hearing more about it in the future, in bare naked detail. Enjoy!

Update

Someone commented for an example. The ones given were a bit abstract, so I’ve posted a more concrete .




# Acts As State Machine Examples
#
# Of note:
# * For every 'state' you define, a query method ? is created
# * For every 'event' you define, a method ! is created
# * Entry, exit, and guard actions can be defined either as a Proc object or
# as a symbol. The symbol should be the name of an instance method on the
# model.


# A simple transition
#
# +---------+ run +---------+
# | idle |-------->| running |
# +---------+ +---------+
#
class Machine < ActiveRecord::Base
acts_as_state_machine :initial => :idle

state :idle
state :running

event :run do
transitions :from => :idle, :to => :running
end
end


# A loopback transition
# +---------+
# | |------+
# | idle | | timeout
# | |<-----+
# +---------+
#
class Machine < ActiveRecord::Base
acts_as_state_machine :initial => :idle

state :idle

event :timeout do
transitions :from => :idle, :to => :idle
end
end


# A transition with enter and exit actions
# +---------+ +---------+
# | | run | |
# | idle |-------------->| running |
# | | stop_timer | |
# +---------+ do_work +---------+
#
class Machine < ActiveRecord::Base
acts_as_state_machine :initial => :idle

state :idle
state :running, :enter => Proc.new { |o| o.stop_timer('idle'); o.do_work() },
:exit => :exit_running

event :run do
transitions :from => :idle, :to => :running
end

def stop_timer(timer)
end

def do_work
end

def exit_running
end
end


# Transition guards
# +---------+ +---------+
# | | run[t] | |
# | idle |-------------->| running |
# | | stop_timer | |
# +---------+ do_work +---------+
# | ^
# | |
# +_____+
# run[f]
#
class Machine < ActiveRecord::Base
acts_as_state_machine :initial => :idle

state :idle
state :running, :enter => Proc.new { |o| o.stop_timer('idle'); o.do_work() }

event :run do
transitions :from => :idle, :to => :running, :guard => Proc.new {|o| o.can_go? }
transitions :from => :idle, :to => :idle
end

def stop_timer(timer)
end

def do_work
end

def can_go?
# Returns true or false, state advances accordingly
end
end
阅读(1371) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~