DEV Community

Germán Alberto Gimenez Silva
Germán Alberto Gimenez Silva

Posted on • Originally published at rubystacknews.com on

🚦 Understanding State Machines in Ruby: Concepts, Examples & the Best Gems

Understanding State Machines in Ruby: Concepts, Examples & the Best Gems
Understanding State Machines in Ruby: Concepts, Examples & the Best Gems

November 21, 2025

State machines are one of the cleanest and most reliable ways to model workflows in software. If your system needs to move through predictable steps — orders, payments, approvals, devices, tickets — a state machine ensures everything transitions cleanly and safely.

In Ruby and Rails, they’re extremely powerful. Here’s a quick guide to the concept, a simple example, and a comparison of the top gems.


🔹 What Is a State Machine?

Article content

A Finite State Machine (FSM) models four things:

✔ States (e.g., pending, approved, rejected)

✔ Events that trigger transitions

✔ Valid paths between states

✔ Optional guards and callbacks

It protects your system from invalid behavior — like shipping an order before being paid.


🔹 Simple Example (No Gem)


class Order
  STATES = %i[pending paid shipped delivered].freeze
  attr_reader :state

  def initialize
    @state = :pending
  end

  def pay ; transition_to(:paid) if state == :pending; end
  def ship ; transition_to(:shipped) if state == :paid; end
  def deliver ; transition_to(:delivered) if state == :shipped; end

  private
  def transition_to(new_state)
    puts "Transition: #{state} → #{new_state}"
    @state = new_state
  end
end

Enter fullscreen mode Exit fullscreen mode

Great for understanding the idea — but real apps benefit from a gem.


🔹 The Most Popular Ruby State Machine Gems

1⃣ AASM (Recommended for Most Rails Apps)

One of the most widely adopted solutions in the Ruby ecosystem.

Pros

  • Clean, readable DSL
  • Rails-friendly
  • Guards, callbacks, multiple machines
  • Good community support

Cons – Can get complex in large workflows – DSL flexibility can lead to messy code if not organized

Example:


aasm do
  state :pending, initial: true
  state :paid
  state :shipped

  event :pay { transitions from: :pending, to: :paid }
  event :ship { transitions from: :paid, to: :shipped }
end

Enter fullscreen mode Exit fullscreen mode

2⃣ state_machine (Classic but Unmaintained)

The original DSL many people loved.

Pros

  • Beautiful DSL
  • Mature and stable historically

Cons – Not actively maintained – Many forks, fragmented ecosystem

Use for legacy apps — not ideal for new ones.


3⃣ Statesman (Audit-Friendly Workflows)

A different philosophy: transitions are stored in a database table.

Pros

  • Excellent for compliance and history tracking
  • Clean architecture
  • Great for long, complex workflows

Cons – More boilerplate – No model callbacks – Might be too heavy for simple apps


4⃣ Workflow (Lightweight Ruby FSM)

Perfect if you want something tiny and fast.

Pros

  • Small and simple
  • Great for non-Rails Ruby apps

Cons – Less popular in Rails – Fewer advanced features


🔹 So… Which One Should You Use?

GemBest ForProsCons AASM Most Rails appsEasy, powerfulCan get complex state_machine Legacy appsClean DSLUnmaintained Statesman Auditable workflowsLogs + structureMore boilerplate Workflow Lightweight RubySimple + fastFewer features


🚀 Final Thoughts

State machines bring clarity and safety to your domain logic. If you’re building a modern Rails app today, AASM is usually the cleanest choice. For audit-heavy systems, Statesman stands out.

Article content

Top comments (0)