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 endendFeatures
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 failureorder.can_confirm?checks if transition is valid
Callbacks
before_transitionandafter_transitionhooks- 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 endend
# ScopesOrder.pending.countOrder.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