Skip to content

Instantly share code, notes, and snippets.

@sintaxi
Created November 26, 2008 10:53
Show Gist options
  • Save sintaxi/29357 to your computer and use it in GitHub Desktop.
Save sintaxi/29357 to your computer and use it in GitHub Desktop.
module StateMachine
def self.included(klass)
klass.extend ClassMethods
end
def self.wrap_method(klass, name)
original_method = "original_#{name}"
before_method = "before_#{name}"
after_method = "after_#{name}"
body = %{
alias_method :#{original_method}, :#{name}
def #{name}
before_each if respond_to?(:before_each)
#{before_method} if respond_to?(:#{before_method})
change_state(\"#{name}\")
result = #{original_method}
log_state(\"#{name}\")
#{after_method} if respond_to?(:#{after_method})
after_each if respond_to?(:after_each)
result
end
}
klass.class_eval body
end
module ClassMethods
attr_accessor :states
def state_machine(*args)
@states = []
yield
end
def state(name, args={}, &block)
unless block_given?
create_state(name, args)
else
create_state_method(name, &block)
end
end
def create_state(name, args)
#a = [name, args]
@states << name
end
def create_state_method(name, &block)
define_method(name, block)
StateMachine.wrap_method(self, name)
end
def before(name, &block)
if name == :each
define_method("before_each", block)
else
define_method("before_#{name}", block)
end
end
def after(name, &block)
if name == :each
define_method("after_each", block)
else
define_method("after_#{name}", block)
end
end
end
def change_state(name)
puts "mark_state...#{name}"
end
def log_state(name)
puts "logging state...#{name}"
end
end
class Light
include StateMachine
state_machine do
state :new
state :green
state :amber
state :red
state :complete
end
state :new do
puts "I am new"
end
state :green do
puts "processing green"
end
state :amber do
puts "processing amber"
end
state :red do
puts "processing red"
true
end
state :complete do
puts "im done"
end
before :each do
#...
end
before :red do
#...
end
end
l = Light.new
l.red
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment