# Model Patterns

Builds rich domain models with business logic, concerns, and proper associations...

- Repository: https://github.com/ThibautBaissac/rails_ai_agents (671 stars)
- Category: Design
- License: MIT
- Last updated: 2026-06-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add ThibautBaissac/rails_ai_agents --skill model-patterns -g -a claude-code -y`
Codex: `npx skills add ThibautBaissac/rails_ai_agents --skill model-patterns -g -a codex -y`
Cursor: `npx skills add ThibautBaissac/rails_ai_agents --skill model-patterns -g -a cursor -y`
Gemini CLI: `npx skills add ThibautBaissac/rails_ai_agents --skill model-patterns -g -a gemini-cli -y`

## Description

Builds rich domain models with business logic, concerns, and proper associations following the fat-models-over-service-objects philosophy. Use when creating models, adding validations, scopes, callbacks, business logic methods, or associations. WHEN NOT: Controller/routing work (use crud-patterns), concern extraction (use concern-patterns), state record design (use state-records).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Model Patterns (37signals)

Rich domain models over service objects. Business logic lives in models, not in separate service classes.

## Project knowledge

**Tech Stack:** Rails 8.2 (edge), UUIDs everywhere, database-backed everything (no Redis)
**Patterns:** Heavy use of concerns, default values via lambdas, Current for context

**Commands:**
```bash
bin/rails generate model Card title:string body:text board:references:uuid
bin/rails generate migration AddColorToCards color:string
bin/rails db:migrate
bin/rails test test/models/
bin/rails console
```

## Rich model vs service object

```ruby
# BAD -- service object
class CloseCardService
  def initialize(card, user)
    @card = card
    @user = user
  end

  def call
    ActiveRecord::Base.transaction do
      @card.create_closure!(user: @user)
      @card.track_event("card_closed", user: @user)
    end
  end
end

# GOOD -- rich model
class Card < ApplicationRecord
  include Closeable

  def close(user: Current.user)
    create_closure!(user: user)
    track_event "card_closed", user: user
    notify_recipients_later
  end
end

# Controller simply calls:
@card.close
```

## Model structure

Order within a model:

```ruby
class Card < ApplicationRecord
  # 1. Concern includes
  include Assignable, Closeable, Eventable, Searchable, Watchable

  # 2. Associations
  belongs_to :account, default: -> { board.account }
  belongs_to :board, touch: true
  belongs_to :column, touch: true
  belongs_to :creator, class_name: "User", default: -> { Current.user }

  has_many :comments, dependent: :destroy
  has_many :assignments, dependent: :destroy
  has_one :closure, dependent: :destroy

  # 3. Validations
  validates :title, presence: true
  validates :status, inclusion: { in: %w[draft published archived] }

  # 4. Enums
  enum :status, { draft: "draft", published: "published", archived: "archived" }, default: :draft

The rest: https://github.com/ThibautBaissac/rails_ai_agents/blob/HEAD/.claude_37signals/skills/model-patterns/SKILL.md
