Jun 4 2012

Managing States using state_machine

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).

2 Comments

  1. Sudhindra Rao

    Hi,
    All your gists seem to be broken. Can you please fix them?

    -Thanks
    Sudhindra

Leave a Comment

Join the discussion. Do not worry, your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>