Ruby on Rails recently added a built-in ActiveRecord::StateMachine implementation and even more recently tied it in to ActiveRecord. And, for being a built-in library, it’s pretty damned fully-featured. Really, if this one doesn’t do it for you, then you probably need to write it yourself, anyway.
And, if you’re thinking that you don’t know what a state machine is, or think that you’ve never used one, think again. If you’ve ever used the restful_authentication plugin, you’ve probably used a state machine. In that library, Users can be pending, active, inactive … It’s all the same object, just acting differently depending on its current situation. That, in a nutshell, is a state machine.
Let’s start with an example that most people might recognize:
class TrafficLight < ActiveRecord::Base
include ActiveRecord::StateMachine
state_machine do
state :red
state :green
state :yellow
event :change_color do
transitions :to => :red, :from => [:yellow], :on_transition => :catch_runners
transitions :to => :yellow, :from => [:green]
transitions :to => :green, :from => [:red]
end
end
def catch_runners
puts "That'll be $250."
end
end
light = TrafficLight.new
light.current_state #=> :red
light.change_color! #=> true
light.current_state #=> :green
light.change_color! #=> true
light.current_state #=> :yellow
light.change_color! #=> true
"That'll be $250."
So, that’s a basic state machine. The light changes from red to green to yellow to red. That’s it. It’s a boring life for a stop light. Certainly, this isn’t a glamorous example, but there are some interesting points here:
- The initial state for the TrafficLight is red, which is the first state defined.
- On a successful transition to red (from yellow), the local
catch_runnersmethod is executed. - The model acts differently depending on its current state, for instance, the
change_color!method has a different action depending on the current color of the light.
And that’s not all. The built-in StateMachine also supports success callbacks per event, enter and exit callbacks per state, guards on transitions, and a lot more:
event :sample, :success => :we_win do; ...; end
state :open, :enter => [:alert_twitter, :send_emails], :exit => :alert_twitter
event :close do # You may only close the store if the safe is locked!! transitions :to => :closed, :from => :open, :guard => :safe_locked? end
So, if you’ve ever used the AASM plugin, you’ll probably feel right at home here with the ActiveRecord::StateMachine. I’m finding myself quite comfortable. In fact, I just might relocate.
Photo credit: Go and Stop

Excellent… will it be backported for 2.3.x? or is it a 3.0-only feature?
– nachokb
It’s interesting that they have rolled this into core, where in the past they have extracted such items such as “acts_as_tree” into plugins.
I’m pleased to see the influence of AlterEgo (http://alter-ego.rubyforge.org/), in the form of state-based polymorphism and my much-abused traffic light example, making it into ActiveRecord :-)
Love it!
Available…. when ?
@nachokb and @elad: Exactly when it will be released into a formal release, I can’t say for sure. It is already in the mainline release branch, so I would assume that it would hit the next 2.3.x release unless 3.0 were to be released before that time. It shouldn’t be necessary to back-port.
@avdi: Thanks for stopping in and looking this over. I must admit that I’m a state machine junkie. I think alter-ego is probably the closest to the true Gang of Four implementation that I’ve seen of a SM in Ruby. Great job on it. I certainly apologize for the traffic light example, it was inspired by the test cases in Rails for the new StateMachine module. Which, probably, was inspired by your Alter Ego post. :)
I’m really pleased that the core has a state machine, however I think there is a better impl which is http://github.com/sbfaulkner/has_states/tree/master, you can have multiple state columns and it overcomes the following limitations with aasm (and possibly AR:SM), “Validations and guards were redundant, transitions were not observable and direct manipulation of state attributes did not result in transitions.” The latter especially useful in RESTful manipulation of states. Maybe these limitations have been overcome in the core version, but at a glace it looked like a port of aasm. Cheers.
[...] The Rails State Machine « Envy Labs A interesting writeup on the new ActiveModel::StateMachine implementation [...]
Am I the only one that has a problem with this? I thought we were supposed to be taking bloat out of core rather than putting more into it. A state machine implementation really doesn’t seem like core functionality to me. Additionally, I might prefer one state machine implementation over the other.
I don’t get it.
Dan: You’re not the only one. I don’t get it too.
@dan I think it’s important to note that a simple state machine implementation would likely be quite useful internally to core. Often, SMs can clean up logic and make intent more easily conveyed. But, as far as I’ve seen, it hasn’t yet been used anywhere in the core.
@simmsy I can certainly agree with some of your feelings towards AASM, although I’m not sure I’d be on board with “manipulation of state attributes” resulting in transitions. That seems a little awkward to me. I would rather my state attribute be closed to the world and entirely private to the instance. I prefer always transitioning my SMs via a transition method, which allows for callbacks and more complex logic than just change A to B. It seems like bad form to potentially allow an external party to randomly define your state value.
@nathaniel: No apology needed, since I think I lifted the traffic light example from the Gang of Four :-)
I also don’t like it as a core feature, hope it would be extracted into a plugin.
@DanPickett: A state machine is such a frequently used pattern that having one in the core seems like a bonus. If you’re a savvy developer with a preferred implementation you’re still welcome to use whatever you like.
I think we have to look at this addition in context of the other changes in Rails 3. Specifically, Rails 3 is becoming more modular so you’ll be able to take what you need and leave what you don’t. If you look at the example, he had to mix in the functionality – it wasn’t bloating AR::Base by default. With that in mind, it’s pretty much a win all around. State machines are so common (multi-step processes like signups and checkouts are the norm), it’s great to have the functionality in the framework. Rails will always let you choose something else but having an officially supported state machine implementation out of the box is a nice bonus.
austinfromboston and Christian Romney++ Glad I refreshed the article I’d had open for awhile before replying :-)
As long as it’s a mixin, it’s a welcome addition to me. One less plugin needed for pretty much every app I have with user signups, and it’s a well-defined, archetypal pattern where a stable API in core can stand as a reference implementation.
[...] The Rails State Machine Rails edge recently added built-in state machine functionality. Here’s a few examples of how you might take advantage of this feature. [...]
I’m glad to see this getting added to the core. A preferred state machine is a win.
I’m happy too! …never have to worry about it not working with future versions..
Add me to the list of guys who don’t get why this is in core
What I don’t get is why this is in core *but authentication isn’t*.
It would be nicer as a plugin, but I’m not fussed. These defaults are what makes Rails so great! People are more likely to use something built into Rails and compatibility maintained between versions. Makes things easier for new developers joining a project. I read somewhere that 3.0 will include a background task system too, which will be great!
[...] ActiveRecord::StateMachine (announced) [...]
I think core should have released this as a gem.
Between app templates, geminstaller and config.gems any pain associated with installing gems is reduced to almost nothing. It would add seconds to an app developers time, but it will add to the burden of developers who want to contribute to rails since it’s one more thing that could break.
And if we’re talking about adding to the framework, how about pulling in will_paginate. Every rails app I’ve ever seen uses will_paginate, and there are no other viable alternatives to my knowledge, nor are there any serious arguments about it’s implementation. But will_paginate is not in core.
From a support standpoint, I think rails core just added more work for themselves unecessarily. If it were a gem, they could open up the core contributor list to people like authors of other state_machine gems, managed it in a separate lighthouse project and if it fails, let it die gracefully, like acts_as_nested_set. If this makes it into a release, it’s just one more piece of noise that will take up core members time and divert attention from making less controversial parts of the framework better.
It’s quite interesting, thanks Nathaniel. But as Jeff Dean, I don’t see the point to include this in the core framework. This is making it more fat. Plugin or gem are better place as it’s fit for specific situations.
Totally agree with Jeff and Renoke. Even this can be very useful, it is probably better to be released as a gem. What about ActiveStateMachine ? :)
[...] The Rails State Machine « Envy Labs [...]
Most of us are coding state machine support code into models anyway. after_saves and the like running conditionally in our models are doing what this DSL can express more elegantly. I’m hanging out for the controller equivalent for stateful navigation to clean up before_filter support logic.
Would core benefit from inclusion? Six of one, half a dozen of the other. Simply ‘six’ is more direct IMHO.
[...] The Rails State Machine « Envy Labs [...]
I like it in the core, i use it quite often and a i think simple state machine fit well in activerecord.
Thanks for the post.
Interesting. Please consider taking my 5 minute survey on models that includes questions on state machines use.
http://spreadsheets.google.com/viewform?hl=en&cfg=true&formkey=cFZqeVg0cGZzZkZpSFl1SVNjaFI2UEE6MA..
http://spreadsheets.google.com/viewform?hl=en&cfg=true&formkey=cFZqeVg0cGZzZkZpSFl1SVNjaFI2UEE6MA..
any information on how the state machine is implemented inside ruby?
your example doesn’t work anymore.
You need to change:
include ActiveRecord::StateMachine
to:
include ActiveModel::StateMachine
@silas Thanks. The post has been updated to reflect the move to ActiveModel from ActiveRecord.
Actually I was incorrect. ActiveModel isn’t persistent while ActiveRecord is.
It appears that as of Rails 2.3.4 this functionality is not included. Is this slated for 2.3.x or 3.0 ?
I also agree that this little utility should be in the core. Come on, you always end up needing a state machine, one way or another.
Here you have a state pattern based alternative that integrates with ActiveRecord: http://github.com/dcadenas/active_record_state_pattern
The library intentionally follows the classic state pattern implementation (no state mixins, classical delegation to simple state classes, etc.) believing that by doing so we increase flexibility (internal DSL constraints vs plain object oriented Ruby power), simplicity and clarity.
Any update about when this is slated for release – 3.0? Where is the official ‘timeline’ for release feature sets – lighthouse?
I don’t get why people are complaining about why its in core… Its not a big deal! It’s a mixin! Its not in by default, it doesn’t bloat anything, its just an extra piece of love that you can use if you want. Every project I’ve ever done needed a state machine, one way or another – so I welcome this functionality with open arms.
This looks great but I too am wondering if I should wait for a 2.3.x minor release or if this is a 3.0 feature. I spent a little while trying to find that information with no luck.
As per the rails 3.0 beta release notes ActiveRecord::StateMachine has been removed from the rails 3.0 release. Does anyone know whether this module will be released as a separate gem?
[...] The Rails State Machine Ruby on Rails recently added a built-in ActiveModel::StateMachine implementation and even more recently tied it in to ActiveRecord. And, for being a built-in library, it’s pretty damned fully-featured. [...]
@tonymi — apparently Jeremy took it out, saying something to the effect “a StateMachine implementation is not needed — you can just use Ruby”. Not exactly sure what he means by this though…
there is a gem called Transitions that uses the exact same syntax: https://github.com/qoobaa/transitions