Skip to content

Instantly share code, notes, and snippets.

@vidarh
Created January 22, 2024 05:29
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 vidarh/04b7d54c94f1f03b4cf084081166d812 to your computer and use it in GitHub Desktop.
Save vidarh/04b7d54c94f1f03b4cf084081166d812 to your computer and use it in GitHub Desktop.
Trivial state machine example
module StateMachine
def self.included(base) = base.extend(ClassMethods)
def transition_to(to)
before = self.class.do_before_transition(state)
send(before) if before
return @state = to
end
def transition(transitions)
curstate = state
transitions.each do |from, to|
transition_to(to) if Array(from).member?(curstate)
end
return nil
end
def unless_state(*states) = states.member?(state) || yield
def if_state(*states) = states.member?(state) && yield
def state = @state || (self.respond_to?(:initial) ? initial : nil)
module ClassMethods
def before(from, method) = (@@before ||= {})[from] = method
def do_before_transition(state) = (@@before||={})[state]
def event(name, &block)
define_method(name, block)
# Do other stuff for introspection here.
end
end
end
class Vehicle
include StateMachine
def initialize
@auto_shop_busy = false
end
def initial = :parked
before(:parked, :put_on_seatbelt)
def park = transition([:idling, :first_gear] => :parked)
def ignite = transition(:parked => :idling)
def idle = transition(:first_gear => :idling)
def shift_up = transition(
:idling => :first_gear,
:first_gear => :second,
:third_gear => :third
)
def crash = unless_state(:parked, :stalled) do
transition_to(:stalled) if !passed_inspection?
end
def moving? = unless_state(:parked, :stalled, :idling)
def speed = if_state(:idling, :first_gear) ? 10 : nil
def repair = if_state(:stalled) do
transition_to(:parked) unless auto_shop_busy
end
def passed_inspection? = false
def put_on_seatbelt = puts "putting on seatelt"
end
v = Vehicle.new
p v.state
v.ignite
p v.state
puts "Crashing"
v.crash
p v.state
v.park
p v.state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment