🔥

Campfire(37signals)

DHHスタイルの教科書 — Rails基本機能だけで作ったリアルタイムチャットアプリ

GitHub: basecamp/once-campfire

Campfireは37signalsのONCEブランドでリリースされたインストール型チャットアプリです。Rails基本機能のみでリアルタイムチャットを実装しており、DHHコーディングスタイルの最も完成された実戦例です。

詳細なディレクトリ構造とパターン分析については韓国語版を参照してください。カスタムアクションゼロのCRUDコントローラ、ブーリアンの代わりにレコードで状態管理、has_secure_passwordによるDeviseなしの認証、Concern分離によるモデル肥大化防止、Currentパターン、6つの専用Action Cableチャンネルが含まれます。

ONCE哲学がコードに直接反映されています:SQLiteデフォルト、Solid Queue/Cache/Cable、OAuthなしのメール/パスワード、Kamal単一サーバーデプロイ。

構造ダイアグラム

CRUDマッピングパターン

一般的な方式 (カスタムアクション)
RoomsController
def index ... end
def show ... end
def create ... end
def close ... end
def reopen ... end
def archive ... end
def ban_user ... end
7+アクション = Fat Controller
Campfire方式 (CRUD分離)
RoomsController index / show / create
Rooms::ClosedsController create / destroy
Messages::BoostsController create / destroy
Users::BansController create / destroy
各コントローラがCRUDのみ = Skinny Controllers

状態 = レコード (ERD)

👤 User has_secure_password
id, email_address, password_digest, name, role
has_many
has_many
has_many
🚫
user_id
administrator_id
created_at
存在 = ブロック済
message_id
user_id
content
存在 = ブースト済
🔗
room_id
user_id
created_at
存在 = 参加中
ポイント: <strong>is_banned: boolean</strong>の代わりに<strong>Banレコードの存在有無</strong>で状態判断
誰が、いつ変更したか自然に記録される

Concern分離構造

👤 Userモデル concerns/ ↗
include User::Bannable ブロック
include User::Mentionable @メンション
include User::Role 役割
include User::Transferable 移行
💬 Messageモデル concerns/ ↗
include Message::Broadcasts Cable
include Message::Pagination ページ
include Message::Searchable 検索

Action Cableチャンネル構造

キーポイント

1

GitHubでbasecamp/once-campfireリポジトリを開く

2

config/routes.rb → リソースネスティングとCRUDマッピングパターンを確認

3

app/controllers/rooms/ → closeds、opens、directsコントローラを分析

4

app/models/user.rb → has_secure_password認証を確認(Deviseなし)

5

app/models/user/*.rb → Concern分離パターンを学習

6

app/models/ban.rb、boost.rb → 状態をレコードで管理するパターンを確認

7

app/channels/ → Action Cable 6チャンネル構造を分析

8

app/javascript/controllers/ → Stimulusコントローラパターンを確認

9

自分のプロジェクトにパターンを一つずつ適用してみる

メリット

  • DHHスタイルの最も完成された実践例
  • CRUDマッピングパターンを実際のコードで確認可能
  • Concern分離の適切な規模感を把握
  • Action Cable実戦実装6チャンネルを参考
  • ONCE哲学のシンプルなアーキテクチャを体感
  • Stimulusコントローラ~30個の実戦パターン

デメリット

  • シングルテナントのためマルチテナントアプリに直接適用が困難
  • 小規模チャットアプリのため大規模サービスとは異なる
  • Minitest + Fixtures — RSpecユーザーには馴染みがない場合がある
  • ネイティブCSS使用 — Tailwindトレンドとは異なる
  • ONCEライセンスでフォーク/修正制限

ユースケース

CRUDマッピング: rooms/closeds_controller.rb — 部屋閉じる = create、開く = destroy CRUDマッピング: messages/boosts_controller.rb — ブースト = create/destroy CRUDマッピング: users/bans_controller.rb — 禁止 = create/destroy レコード状態: Ban、Boost、Membership — ブーリアンの代わりにレコード Concern分離: User::Bannable、Message::Broadcastsなど Currentパターン: リクエストスコープのグローバル状態管理 Deviseなしの認証: has_secure_password + Authentication concern