rails-state-machines
Implement state machines for managing complex workflows and state transitions. Use when models have distinct states with defined transitions, business rules for state changes, or event-driven workflows.
$ Installieren
git clone https://github.com/nekorush14/dotfiles /tmp/dotfiles && cp -r /tmp/dotfiles/configs/claude/skills/rails-state-machines ~/.claude/skills/dotfiles// tip: Run this command in your terminal to install the skill
SKILL.md
name: rails-state-machines description: Implement state machines for managing complex workflows and state transitions. Use when models have distinct states with defined transitions, business rules for state changes, or event-driven workflows.
Rails State Machines Specialist
Specialized in implementing state machines using AASM gem for complex workflows.
When to Use This Skill
- Managing order workflows (pending â confirmed â shipped â delivered)
- User account states (inactive â active â suspended)
- Document approval processes
- Payment processing states
- Any domain with well-defined state transitions
Core Principles
- Explicit States: Clearly defined states
- Controlled Transitions: Events trigger state changes
- Guards: Validate transitions
- Callbacks: Execute logic on state changes
- Single Source of Truth: State stored in database
Implementation Guidelines
Basic State Machine
# Gemfile
gem 'aasm'
# app/models/order.rb
class Order < ApplicationRecord
include AASM
aasm column: :status do
state :pending, initial: true
state :confirmed, :shipped, :delivered, :cancelled
event :confirm do
transitions from: :pending, to: :confirmed
after do
# WHY: Update confirmation timestamp and send notification
update!(confirmed_at: Time.current)
OrderMailer.confirmation_email(self).deliver_later
end
end
event :ship do
transitions from: :confirmed, to: :shipped
after do
update!(shipped_at: Time.current)
notify_shipping_service
end
end
event :deliver do
transitions from: :shipped, to: :delivered
after do
update!(delivered_at: Time.current)
end
end
event :cancel do
transitions from: [:pending, :confirmed], to: :cancelled
after do
refund_payment
restore_inventory
end
end
end
private
def notify_shipping_service
# Shipping service integration
end
def refund_payment
# Payment refund logic
end
def restore_inventory
# Restore inventory logic
end
end
Usage in Controllers
class OrdersController < ApplicationController
def confirm
@order = Order.find(params[:id])
if @order.may_confirm?
@order.confirm!
redirect_to @order, notice: 'Order confirmed'
else
redirect_to @order, alert: 'Cannot confirm order'
end
rescue AASM::InvalidTransition => e
redirect_to @order, alert: e.message
end
end
Guards (Conditional Transitions)
class Order < ApplicationRecord
include AASM
aasm do
state :pending, initial: true
state :processing, :completed
event :process do
# WHY: Only allow processing if payment succeeded
transitions from: :pending, to: :processing, guard: :payment_successful?
end
event :complete do
# WHY: Require all items shipped before completion
transitions from: :processing, to: :completed, guard: :all_items_shipped?
end
end
def payment_successful?
payment&.status == 'successful'
end
def all_items_shipped?
order_items.all?(&:shipped?)
end
end
Multiple Transitions for Same Event
class Document < ApplicationRecord
include AASM
aasm do
state :draft, initial: true
state :under_review, :approved, :rejected
event :submit do
# WHY: Route to review if complete, else stay in draft
transitions from: :draft, to: :under_review, guard: :complete?
transitions from: :draft, to: :draft, unless: :complete?
after do
notify_reviewers if under_review?
end
end
event :review do
transitions from: :under_review, to: :approved
transitions from: :under_review, to: :rejected
end
end
def complete?
title.present? && content.present?
end
end
Error Handling
class Order < ApplicationRecord
include AASM
aasm do
state :pending, initial: true
state :processing, :completed, :failed
event :process do
transitions from: :pending, to: :processing
error do |e|
# WHY: Log error and transition to failed state
Rails.logger.error("Order processing failed: #{e.message}")
self.error_message = e.message
may_fail? ? fail! : raise
end
after do
charge_payment
end
end
event :fail do
transitions from: :processing, to: :failed
end
end
def charge_payment
# May raise exception
PaymentService.charge(self)
end
end
State Scopes
class Order < ApplicationRecord
include AASM
aasm do
state :pending, initial: true
state :confirmed, :shipped, :delivered, :cancelled
# ... events ...
end
# Automatically creates scopes
# Order.pending
# Order.confirmed
# Order.shipped
end
# Usage
Order.confirmed.where(user: current_user)
State Queries
# Check current state
order.aasm_state # => "confirmed"
order.pending? # => false
order.confirmed? # => true
# Check possible transitions
order.aasm.states(permitted: true) # => [:shipped, :cancelled]
# Check if transition allowed
order.may_ship? # => true
order.may_deliver? # => false
# Get current event
order.aasm.current_event # => :ship
Testing State Machines
# spec/models/order_spec.rb
RSpec.describe Order, type: :model do
describe 'state machine' do
let(:order) { create(:order) }
it 'starts in pending state' do
expect(order).to be_pending
end
describe '#confirm' do
it 'transitions from pending to confirmed' do
expect { order.confirm! }
.to change { order.aasm_state }
.from('pending').to('confirmed')
end
it 'updates confirmed_at timestamp' do
expect { order.confirm! }
.to change { order.confirmed_at }
.from(nil)
end
it 'sends confirmation email' do
expect(OrderMailer).to receive(:confirmation_email)
order.confirm!
end
end
describe '#ship' do
it 'cannot ship pending order' do
expect(order.may_ship?).to be false
end
it 'can ship confirmed order' do
order.confirm!
expect(order.may_ship?).to be true
end
end
end
end
Tools to Use
Read: Read existing state machine codeWrite: Create new state machine modelsEdit: Modify state machinesBash: Run tests and migrations
Bash Commands
# Add AASM gem
bundle add aasm
# Generate migration for state column
bundle exec rails generate migration AddStatusToOrders status:string
# Run tests
bundle exec rspec spec/models/order_spec.rb
Workflow
- Identify States: Define all possible states
- Define Events: List state transitions
- Write Tests: Test each transition
- Implement State Machine: Add AASM to model
- Add Callbacks: Implement after/before logic
- Add Guards: Implement conditional transitions
- Test: Verify all transitions work
Related Skills
rails-model-design: Understanding model structurerails-service-objects: Complex transition logicrails-background-jobs: Async operations after transitionsrails-rspec-testing: Testing state machines
Coding Standards
TDD Workflow
Follow TDD Workflow
Key Reminders
- Define initial state explicitly
- Use guards for conditional transitions
- Add callbacks for side effects
- Test all transitions and guards
- Use
may_event?to check before transitioning - Handle
AASM::InvalidTransitionexceptions - Keep state machine logic in the model
- Use scopes for querying by state
Repository

nekorush14
Author
nekorush14/dotfiles/configs/claude/skills/rails-state-machines
2
Stars
0
Forks
Updated2d ago
Added1w ago