Upcoming and OnDemand Webinars View full list

Managing States using state_machine

Gregg Rothmeier

Often times the state of an object is tracked through boolean attributes, but this solution doesn’t scale well since each new state requires a new column in the table along with logic to govern how the states change. If you have a model which you need to track the states of, the state_machine gem can be a great solution. It stores the state of the object in a string-type column (state in the example below), and adding states and transitions is as easy as adding a couple lines of code to the model.

Here I’ve created a ruby model to describe my dogs.

So with this in place we can fire up irb and create a new instance of the Dog class:

As you can see, since we set initial: :sleeping as an argument in the call to state_machine all new instances are created with the state of "sleeping". One of the nice features of state_machine is how easy it is to define events and how states should change as a result of calling an event. For example, gonzo is sleeping now, so let’s see if we can go for a walk:

state_machine provides nice helper methods named can_<event name>? in order to check if calling the event has a transition defined for the current state. Since gonzo’s asleep, he can’t go for a walk, so if we try calling gonzo.walk we get false. First things first, we have to wake him up before taking him on a walk:

When declairing a state, you can pass it a block to define other methods as I’ve done with the hungry method. Since a dog is willing to have a cheese-snack any time of day, we can use the following to return true for that method call when in any states other than “sleeping”.

While this example is obviously a simple case, it’s easy to see how this approach scales well to more complicated state relationships. The state_machine gem integrates with a number of libraries including ActiveModel classes, ActiveRecord models, DataMapper resources and Mongoid models. Another feature that some may like is its support for generating a directed graph using the graphviz library. If you ever need to track the state of a record, state_machine is definitely worth a look. What’s your preferred method for tracking states?

Image is my own (it’s Gonzo).

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project