📖

Writebook(37signals)

ONCEブランドの出版ツール — delegated_typeと編集履歴管理の教科書

GitHub: projectcues/writebook(ONCE公式コード)

Writebookは37signalsのONCEブランドでリリースされたWeb基盤の出版ツールです。本を書いたり、チャプターを管理したり、オンラインで出版できます。

詳細なディレクトリ構造とパターン分析については韓国語版を参照してください。多態コンテンツ管理のためのdelegated_type(Page/Section/Picture)、編集履歴追跡のためのEditレコード、権限管理のためのAccessレコード(reader/editor)、DB基盤のSessionモデル、Campfireと同じAuthentication concernパターン、Publication・Bookmark・MoveリソースのCRUDマッピングパターンが含まれます。

構造ダイアグラム

delegated_type構造 (ERD)

📚 Book
title, theme, published, slug
has_many :leaves
🍃 Leaf delegated_type :leafable
book_id, title, position, status, leafable_type, leafable_id
delegated_type :leafable, types: [Page, Section, Picture]
ポイント: <strong>STI</strong>(単一テーブル)と異なり、各タイプが<strong>独自のテーブル</strong>を持つ
Leafが共通インターフェース役割 (title, position, status)

状態 = レコード (Edit / Access / Session)

✏️ Edit
leaf_id
action (revision|trash)
leafable_type, leafable_id
created_at
編集のたびにレコード作成
previous / nextで履歴探索
🔑 Access
user_id
book_id
level (reader|editor)
存在 = アクセス可能
Punditなしで権限管理
🔐 Session
user_id
token (secure_token)
user_agent, ip_address
last_active_at
セッションもDBレコード
Deviseなしでセッション管理

認証フロー (Campfireと同一パターン)

🌐 ブラウザリクエスト
Authentication concern
before_action :require_authentication
authentication.rb ↗
Cookieにsession_tokenあり
Cookieなし
restore_authentication
Session.find_by(token:)
→ session.resume
→ Current.user = session.user
request_authentication
redirect_to new_session_url
ポイント: Campfireと<strong>完全に同一のパターン</strong> — 37signalsで社内再利用される認証構造

Campfire vs Writebook

用途
リアルタイムチャット
Web出版
認証
Authentication
同一
多態性
STI (Room)
delegated_type
履歴
なし
Editレコード
アクセス制御
Membership
Access (reader/editor)
リアルタイム
Action Cable 6チャンネル
なし
ジョブキュー
Solid Queue
Resque + Redis

キーポイント

1

GitHubでprojectcues/writebookリポジトリを開く

2

config/routes.rb → リソース構造とネスティングパターンを確認

3

app/models/leaf.rb → delegated_typeパターンを理解

4

app/models/leafable.rb → 多態インターフェースモジュールを分析

5

app/models/edit.rb → 編集履歴管理パターンを確認

6

app/models/access.rb → アクセス権限レコードパターンを確認

7

app/models/session.rb → DB基盤セッション管理を確認

8

app/controllers/concerns/authentication.rb → Campfireと同一パターンを比較

9

app/controllers/books/publications_controller.rb → CRUDマッピングを確認

メリット

  • delegated_typeパターンの実戦使用事例を学習
  • 編集履歴管理をレコードで実装するパターンを確認
  • Campfireと比較して37signalsの一貫したパターンを把握
  • アクセス制御をレコードで実装するパターン(Punditなし)
  • DB基盤セッション管理の実戦実装
  • slug基盤URLルーティングの優雅な実装

デメリット

  • Resque+Redis使用 — Solid Queueではない旧バージョンスタック
  • Action Cableなし — リアルタイム機能学習にはCampfireが適切
  • Writebookは比較的シンプルなアプリ(CRUD中心)
  • 非公開ONCEライセンス — フォーク/修正制限

ユースケース

delegated_type: Leaf → Page/Section/Picture(多態コンテンツ) Editレコード: 編集履歴をレコードで追跡(previous/next探索) Accessレコード: User-Book間権限管理(reader/editor) Sessionレコード: DB基盤セッション管理(user_agent、ip追跡) Publication CRUD: 出版 = Publicationリソースのupdate Move CRUD: ページ順序変更 = Moveリソースのcreate Authentication concern: Campfireと同一の認証パターンを再利用