Skill
business-logic-coder
Implement business logic with ActiveInteraction and AASM state machines. Routes to specialized skills for typed operations and state management.
From majestic-railsInstall
1
Run in your terminal$
npx claudepluginhub majesticlabs-dev/majestic-marketplace --plugin majestic-railsTool Access
This skill uses the workspace's default tool permissions.
Supporting Assets
View in Repositoryreferences/aasm-patterns.mdreferences/active-interaction.mdSkill Content
Business Logic Patterns
Orchestrator for structured business logic in Rails.
Skill Routing
| Need | Skill | Use When |
|---|---|---|
| Typed operations | active-interaction-coder | Creating business operations, refactoring service objects |
| State machines | aasm-coder | Implementing workflows, managing state transitions |
When to Use Each
ActiveInteraction
Use for operations - things that happen once:
- User registration
- Order placement
- Payment processing
- Data imports
- Report generation
# Example: One-time operation with typed inputs
outcome = Users::Create.run(email: email, name: name)
AASM
Use for state management - things with lifecycle:
- Order status (pending → paid → shipped)
- Subscription state (trial → active → cancelled)
- Document workflow (draft → review → published)
- Task status (todo → in_progress → done)
# Example: Stateful entity with transitions
order.pay! # pending → paid
order.ship! # paid → shipped
Combined Pattern
Often used together - interactions trigger state changes:
module Orders
class Process < ActiveInteraction::Base
object :order, class: Order
def execute
order.process! # AASM transition
fulfill_order(order)
order
end
end
end
Setup
# Gemfile
gem "active_interaction", "~> 5.3"
gem "aasm", "~> 5.5"
Quick Reference
ActiveInteraction:
.run- Returns outcome (check.valid?).run!- Raises on failurecompose- Call nested interactions
AASM:
.event!- Transition or raise.event- Transition or return false.may_event?- Check if transition valid.aasm.events- List available events
Transaction Boundaries
When business logic involves multi-step database operations, enforce proper transaction boundaries.
Atomic Operations
# PROBLEM: Partial failure leaves inconsistent state
def transfer_funds(from, to, amount)
from.update!(balance: from.balance - amount)
to.update!(balance: to.balance + amount) # May fail!
end
# SOLUTION: Transaction wrapper with locking
def transfer_funds(from, to, amount)
ActiveRecord::Base.transaction do
from.lock!
to.lock!
from.update!(balance: from.balance - amount)
to.update!(balance: to.balance + amount)
end
end
Isolation Levels
# Default: READ COMMITTED (each query sees latest committed data)
# REPEATABLE READ: All reads see same snapshot
ActiveRecord::Base.transaction(isolation: :repeatable_read) do
# Consistent reads for reports
end
# SERIALIZABLE: Full isolation (may cause serialization failures)
ActiveRecord::Base.transaction(isolation: :serializable) do
# Strictest isolation, retry on failure
end
Deadlock Prevention
Rules:
- Lock records in consistent order (by ID ascending)
- Keep transactions short
- No user input inside transactions
- No external API calls inside transactions
# PROBLEM: Deadlock risk (inconsistent lock order)
def swap_owners(item_a, item_b)
transaction do
item_a.lock! # Thread 1 locks A
item_b.lock! # Thread 2 locks B -> deadlock!
end
end
# SOLUTION: Consistent lock order
def swap_owners(item_a, item_b)
items = [item_a, item_b].sort_by(&:id)
transaction do
items.each(&:lock!)
# Safe: always locks lower ID first
end
end
Transaction Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Long transactions | Lock contention | Split into smaller units |
| API calls inside | Timeout blocks DB | Call outside, then transact |
| User input inside | Indefinite locks | Validate first, transact last |
| Nested transactions | Savepoint confusion | Use requires_new: true explicitly |
Nested Transactions
# PROBLEM: Inner rollback doesn't work as expected
transaction do
create_order!
transaction do # This is a savepoint, not new transaction
charge_card! # Failure rolls back to savepoint only
end
end
# SOLUTION: Explicit new transaction
transaction do
create_order!
transaction(requires_new: true) do
charge_card! # Failure rolls back only this block
end
end
Related Skills
event-sourcing-coder- Record domain events from state transitions
Similar Skills
Stats
Parent Repo Stars30
Parent Repo Forks6
Last CommitMar 15, 2026