mcpField
B
business-logic-coder

business-logic-coder

github.com/majesticlabs-devDevelopment5065 installsUpdated 7w ago
Repository

About business-logic-coder

A skill for Rails developers structuring business logic as one-time operations or lifecycle-based state management. It covers ActiveInteraction, AASM, and transaction boundaries, isolation, and deadlock prevention.

Key features

  1. 01Route needs to business logic patterns
  2. 02Typed operations with ActiveInteraction
  3. 03State transitions with AASM
  4. 04Transaction boundary and isolation guidance
  5. 05Deadlock prevention and anti-patterns

Use cases

  1. 01Implement registration, ordering, or payment operations
  2. 02Manage order or subscription lifecycles
  3. 03Combine operations with state transitions
  4. 04Design transactions for multi-step database work

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill business-logic-coder

After installing, type/business-logic-coderin Claude Code to confirm it loaded.

Bundled filesreferences/aasm-patterns.mdreferences/active-interaction.md

Details

From the project README

Business Logic Patterns

Orchestrator for structured business logic in Rails.

Skill Routing

NeedSkillUse When
Typed operationsactive-interaction-coderCreating business operations, refactoring service objects
State machinesaasm-coderImplementing 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 failure
  • compose - 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:

  1. Lock records in consistent order (by ID ascending)
  2. Keep transactions short
  3. No user input inside transactions
  4. 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-PatternProblemSolution
Long transactionsLock contentionSplit into smaller units
API calls insideTimeout blocks DBCall outside, then transact
User input insideIndefinite locksValidate first, transact last
Nested transactionsSavepoint confusionUse 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

Comments

Markdown supported