Created
July 25, 2012 17:58
-
-
Save aileron/3177543 to your computer and use it in GitHub Desktop.
ステートマシーンのRuby実装 ほぼ AASMと同じ使い方。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StateMachine | |
class Event | |
def transition opt={from:nil,to:nil,guard:nil} | |
self.ts ||= {} | |
self.ts[ opt[:from] ] = opt if (opt[:from].is_a? String) || (opt[:from].is_a? Symbol) | |
opt[:from].each do |name| | |
ts[name] = opt | |
end if opt[:from].is_a? Array | |
end | |
attr_accessor :ts | |
end | |
class Smg | |
def initialize name,klass | |
self.name = name | |
self.klass = klass | |
self.states = {} | |
smg = self | |
klass.class_eval do | |
define_method :initialize do |*args| | |
super(*args) | |
smg.states.each do |n,s| | |
next unless s[:initial] | |
send s[:enter] if s[:enter] | |
send "#{name}=",n | |
end | |
end | |
end | |
end | |
def state name, opt={enter:nil, initial:nil} | |
self.states[ name ] = opt | |
end | |
def event name, opt={before:nil,after:nil}, &block | |
smg = self | |
event = Event.new | |
event.instance_eval &block | |
klass.class_eval do | |
define_method name do | |
transition = event.ts[ send(smg.name) ] | |
return unless transition | |
return if transition[:guard] && send(transition[:guard]) | |
raise "not state #{transition[:to]}" unless state = smg.states[ transition[:to] ] | |
send opt[:before] if opt[:before] | |
send state[:enter] if state[:enter] | |
send "#{smg.name}=", transition[:to] | |
send opt[:after] if opt[:after] | |
send :save | |
end | |
end | |
end | |
attr_accessor :name | |
attr_accessor :klass | |
attr_accessor :states | |
attr_accessor :instance | |
end | |
def self.included(klass) | |
klass.class.instance_eval do | |
define_method :smg do |name,&block| | |
_smg = Smg.new name,klass | |
_smg.instance_eval &block | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment