Update: Added exceptions for non-existent transitions, and cleaned up a bit.
I’m not a fan of the currently popular Ruby state machine gems (state_machine, AASM). State machines are simple, and these are complicated gems with large APIs.
I had a tinker with implementing the simplest state machine I could in Ruby, with just the features I needed. What follows is what fell out of that tinkering. It’s all in roughly hand-tested form, so it comes with no warranty of any kind. I might expand this into a gem at some point.
First up, it seems like a transition table would be the easiest way to specify a state machine in Ruby. We don’t need a DSL for this:
You’ll see why I use this hash structure below. (It might be nicer to turn this into simple nested arrays, and have the TransitionTable convert to a hash.)
What we want for actually running the state machine is a transition function: a function that takes the current state and some input, and returns the next state and some output.
We can make the transition table behave like that pretty easily:
The State Machine
Now we’ve got a way of specifying states and transitions, we need something to run the state machine.
We can fire up a state machine like this:
Calling Methods on Transitions
I want to include a state machine in my model, and have methods on the model called when transitions happen. I can do something like this:
Drawing a Picture
It’d be great if we could get a state diagram out of this, so:
That requires being able to iterate over the TransitionTable, so we’ll need:
Throwing this and Graphviz at the above transition table gives:
There are a bunch more things I’d like to tinker with: