Back to Work
Library Open Source

SimpleState

Lightweight state machine library for Ruby and Rails. Add explicit state management to any class with minimal configuration and zero dependencies.

The Problem

State machines in Ruby often come with heavy dependencies, complex DSLs, or too much magic. AASM is powerful but heavyweight. Sometimes you need explicit state transitions without the overhead—especially when you want to understand exactly what’s happening.

The Solution

A minimal state machine library that does one thing well: explicit state transitions with callbacks.

class Order
include SimpleState
state_machine :status, initial: :pending do
state :pending
state :confirmed
state :shipped
state :delivered
state :cancelled
event :confirm do
transition from: :pending, to: :confirmed
end
event :ship do
transition from: :confirmed, to: :shipped
end
event :deliver do
transition from: :shipped, to: :delivered
end
event :cancel do
transition from: [:pending, :confirmed], to: :cancelled
end
end
end

Features

Simple DSL

  • Define states and events clearly
  • Multiple source states per transition
  • Guard conditions for conditional transitions

Predicate Methods

  • order.pending?, order.confirmed?, etc.
  • Auto-generated for each state

Bang and Query Methods

  • order.confirm! transitions and raises on failure
  • order.can_confirm? checks if transition is valid

Callbacks

  • before_transition and after_transition hooks
  • Access to from/to states in callback

ActiveRecord Integration

  • Optional module for database-backed state
  • Automatic column detection
  • Scopes for each state (Order.pending, Order.confirmed)
class Order < ApplicationRecord
include SimpleState::ActiveRecord
state_machine :status, initial: :pending do
# ... same DSL
after_transition to: :confirmed do |order|
OrderMailer.confirmation(order).deliver_later
end
end
end
# Scopes
Order.pending.count
Order.shipped.where(created_at: 1.week.ago..)

Design Philosophy

Explicit over implicit. You define every state and every valid transition. No magic state inference.

Zero dependencies. Pure Ruby. Works anywhere Ruby runs.

Predictable behavior. Read the code and know exactly what happens on each transition.

Small API surface. Learn it in 5 minutes. No surprises.

Technical Details

Metaprogramming generates predicate and transition methods at include time. State stored as a simple string attribute. Thread-safe transitions with optional locking support for ActiveRecord.

Transitions are atomic—callbacks run in a transaction when using ActiveRecord integration. Failed guards or callbacks roll back the state change.


Language: Ruby

Dependencies: None (ActiveRecord integration optional)

Compatibility: Ruby 3.0+, Rails 6+ (optional)

License: MIT

Used in: Hive Payroll, Asgard EWA Platform