# Fizzy コードリーディングガイドライン

## はじめに

このガイドラインは、Fizzyのコードベースを効率的に理解するための手引きです。
Rubyに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、Ruby/Ruby on Railsの基本構文と概念を解説します。

### 1.1 プログラム構造

Fizzyは**Ruby on Rails**フレームワークで構築されています。Railsは「設定より規約（Convention over Configuration）」の原則に基づき、ファイル配置やクラス名に厳密な規約があります。

**Railsの基本構造:**

```ruby
# ファイル: app/models/card.rb:1-4
class Card < ApplicationRecord
  include Accessible, Assignable, Attachments, Broadcastable, Closeable, Colored, Commentable,
    Entropic, Eventable, Exportable, Golden, Mentions, Multistep, Pinnable, Postponable, Promptable,
    Readable, Searchable, Stallable, Statuses, Storage::Tracked, Taggable, Triageable, Watchable
```

- **クラス定義**: `class ClassName < ParentClass`で継承を表現
- **ApplicationRecord**: 全モデルの基底クラス（Active Record）
- **include**: モジュール（Concern）の取り込み

### 1.2 データ型と変数

Rubyは動的型付け言語です。変数宣言にはキーワードを使用しません。

```ruby
# ファイル: app/models/current.rb:1-5
class Current < ActiveSupport::CurrentAttributes
  attribute :session, :user, :identity, :account
  attribute :http_method, :request_id, :user_agent, :ip_address, :referrer
```

**変数の種類:**
| 種類 | プレフィックス | 例 |
|------|---------------|-----|
| ローカル変数 | なし | `card`, `user` |
| インスタンス変数 | `@` | `@board`, `@card` |
| クラス変数 | `@@` | `@@count` |
| グローバル変数 | `$` | `$stdout` |
| 定数 | 大文字開始 | `VARIANTS`, `Card` |
| シンボル | `:` | `:name`, `:created_at` |

### 1.3 制御構造

Rubyの制御構造は柔軟で、後置if/unlessが特徴的です。

```ruby
# ファイル: app/controllers/boards_controller.rb:48-56
def update
  @board.update! board_params
  @board.accesses.revise granted: grantees, revoked: revokees if grantees_changed?

  respond_to do |format|
    format.html do
      if @board.accessible_to?(Current.user)
        redirect_to edit_board_path(@board), notice: "Saved"
      else
        redirect_to root_path, notice: "Saved (you were removed from the board)"
      end
    end
```

**STYLE.mdに記載のプロジェクト規約:**
- ガード句よりも展開された条件式を優先
- 早期リターンは、メソッド冒頭で、かつ本体が複雑な場合のみ使用

### 1.4 関数/メソッド定義

```ruby
# ファイル: app/models/card.rb:57-63
def move_to(new_board)
  transaction do
    card.update!(board: new_board)
    card.events.update_all(board_id: new_board.id)
    Event.where(eventable: card.comments).update_all(board_id: new_board.id)
  end
end
```

**メソッド定義のポイント:**
- `def method_name(args)` ... `end`
- `!`サフィックス: 対となるメソッドがある場合のみ使用（STYLE.md規約）
- `?`サフィックス: 真偽値を返すメソッド

### 1.5 モジュール/インポート

Rubyでは`require`/`require_relative`でファイルを読み込みますが、Railsは自動読み込み機構を持っています。

```ruby
# ファイル: app/models/card/eventable.rb:1-6
module Card::Eventable
  extend ActiveSupport::Concern

  include ::Eventable

  included do
```

**Concernパターン:**
- `extend ActiveSupport::Concern`: Rails固有の拡張
- `included do ... end`: インクルード時に実行されるブロック
- `class_methods do ... end`: クラスメソッドの定義

---

## 2. プロジェクト固有の概念

> このセクションでは、当プロジェクト特有の概念を解説します。

### 2.1 フレームワーク固有の概念

**Hotwire (Turbo + Stimulus)**

Fizzyはフロントエンドに**Hotwire**を採用しています。

```javascript
// ファイル: app/javascript/application.js:1-6
import "@hotwired/turbo-rails"
import "@hotwired/hotwire-native-bridge"
import "initializers"
import "controllers"
```

- **Turbo**: サーバーサイドレンダリングを活用したSPA的UX
- **Stimulus**: 軽量なJavaScriptフレームワーク

**Stimulusコントローラー例:**

```javascript
// ファイル: app/javascript/controllers/dialog_controller.js:1-11
import { Controller } from "@hotwired/stimulus"
import { orient } from "helpers/orientation_helpers"
import { isTouchDevice } from "helpers/platform_helpers"

export default class extends Controller {
  static targets = [ "dialog", "focusMouse", "focusTouch" ]
  static values = {
    modal: { type: Boolean, default: false },
    sizing: { type: Boolean, default: true },
    autoOpen: { type: Boolean, default: false }
  }
```

### 2.2 プロジェクト独自のパターン

**Current Attributesパターン**

リクエストスコープのグローバル状態管理:

```ruby
# ファイル: app/models/current.rb:1-18
class Current < ActiveSupport::CurrentAttributes
  attribute :session, :user, :identity, :account
  attribute :http_method, :request_id, :user_agent, :ip_address, :referrer

  def session=(value)
    super(value)
    if value.present?
      self.identity = session.identity
    end
  end

  def identity=(identity)
    super(identity)
    if identity.present?
      self.user = identity.users.find_by(account: account)
    end
  end
```

**マルチテナント構造**

1つのIdentity（認証情報）が複数のAccountに所属可能:

- `Identity`: 認証用（メールアドレス、セッション）
- `User`: Account内でのユーザー表現
- `Account`: テナント（組織）

**非同期処理パターン（STYLE.md準拠）:**

```ruby
# `_later`サフィックス: ジョブをキューに追加
# `_now`サフィックス: 同期実行
def relay_later
  Event::RelayJob.perform_later(self)
end

def relay_now
  # 実際の処理
end
```

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `app/models/{model}.rb` | 単数形のモデルファイル | `card.rb`, `user.rb` |
| `app/models/{model}/{concern}.rb` | モデル専用Concern | `card/eventable.rb` |
| `app/controllers/{resource}s_controller.rb` | 複数形のコントローラー | `cards_controller.rb` |
| `app/controllers/{parent}/{resource}s_controller.rb` | ネストされたコントローラー | `cards/comments_controller.rb` |
| `app/controllers/concerns/*.rb` | コントローラーConcern | `authentication.rb` |
| `app/views/{resource}s/*.html.erb` | ビューテンプレート | `cards/show.html.erb` |
| `app/javascript/controllers/*_controller.js` | Stimulusコントローラー | `dialog_controller.js` |
| `app/jobs/{model}/*_job.rb` | バックグラウンドジョブ | `card/relay_job.rb` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `set_*` | before_actionでのインスタンス変数設定 | `set_board`, `set_card` |
| `*?` | 真偽値を返すメソッド | `authenticated?`, `published?` |
| `*!` | 対となる非破壊メソッドがある場合 | `update!`, `save!` |
| `*_later` | ジョブをキューに追加 | `relay_later`, `clean_data_later` |
| `*_now` | 同期的に実行 | `relay_now` |
| `ensure_*` | 権限チェックのbefore_action | `ensure_permission_to_admin_board` |
| `*able` | Concern/モジュール | `Eventable`, `Searchable` |
| `*Scoped` | スコープ設定用Concern | `BoardScoped`, `CardScoped` |

### 3.3 プログラム分類一覧

| 分類 | ディレクトリ | 役割 |
|------|------------|------|
| モデル | `app/models/` | ビジネスロジック、データアクセス |
| コントローラー | `app/controllers/` | HTTPリクエスト処理 |
| ビュー | `app/views/` | HTMLレンダリング |
| ヘルパー | `app/helpers/` | ビュー用ユーティリティ |
| ジョブ | `app/jobs/` | 非同期処理 |
| メーラー | `app/mailers/` | メール送信 |
| チャンネル | `app/channels/` | WebSocket処理 |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
fizzy-main/
├── app/                      # アプリケーションコード
│   ├── assets/               # アセット（CSS等）
│   ├── channels/             # Action Cable チャンネル
│   ├── controllers/          # コントローラー
│   │   ├── concerns/         # コントローラーConcern
│   │   ├── account/          # アカウント管理
│   │   ├── boards/           # ボード関連
│   │   ├── cards/            # カード関連
│   │   └── ...
│   ├── helpers/              # ビューヘルパー
│   ├── javascript/           # フロントエンドJS
│   │   ├── controllers/      # Stimulusコントローラー
│   │   ├── helpers/          # JSユーティリティ
│   │   └── initializers/     # 初期化処理
│   ├── jobs/                 # バックグラウンドジョブ
│   ├── mailers/              # メーラー
│   ├── models/               # モデル
│   │   ├── concerns/         # 共有Concern
│   │   ├── card/             # Card固有Concern
│   │   ├── board/            # Board固有Concern
│   │   └── ...
│   └── views/                # ビューテンプレート
├── config/                   # 設定ファイル
│   ├── routes.rb             # ルーティング定義
│   ├── database.yml          # DB設定
│   └── initializers/         # 初期化設定
├── db/                       # データベース
│   ├── schema.rb             # スキーマ定義
│   ├── migrate/              # マイグレーション
│   └── seeds.rb              # 初期データ
├── lib/                      # ライブラリ
├── test/                     # テストコード
└── public/                   # 静的ファイル
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `app/models/` | ビジネスロジック | `card.rb`, `board.rb`, `user.rb` |
| `app/controllers/` | リクエスト処理 | `cards_controller.rb`, `boards_controller.rb` |
| `app/views/` | 画面表示 | `cards/show.html.erb` |
| `app/javascript/controllers/` | UI操作 | `dialog_controller.js` |
| `config/routes.rb` | URL設計 | ルーティング定義 |
| `db/schema.rb` | DB構造 | テーブル定義 |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

FizzyはRails標準の**MVC + Concerns**アーキテクチャを採用し、「Vanilla Rails」アプローチを重視しています。

```
┌─────────────────────────────────────────────────────────────┐
│                        Client (Browser/Mobile)               │
├─────────────────────────────────────────────────────────────┤
│  Turbo (Turbo Drive/Frames/Streams) + Stimulus Controllers  │
└────────────────────────────┬────────────────────────────────┘
                             │ HTTP/WebSocket
┌────────────────────────────┴────────────────────────────────┐
│                     Rails Application                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────────┐   │
│  │ Controllers │──▶│   Models    │──▶│ Active Record   │   │
│  │ + Concerns  │   │ + Concerns  │   │                 │   │
│  └─────────────┘   └─────────────┘   └────────┬────────┘   │
│         │                                      │             │
│         ▼                                      ▼             │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────────┐   │
│  │   Views     │   │    Jobs     │   │    Database     │   │
│  │ + Helpers   │   │(Solid Queue)│   │ (MySQL/SQLite)  │   │
│  └─────────────┘   └─────────────┘   └─────────────────┘   │
└─────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| プレゼンテーション | HTTP処理、ビュー生成 | `BoardsController`, `CardsController` |
| ドメイン | ビジネスロジック | `Card`, `Board`, `User` + Concerns |
| インフラ | データ永続化、外部連携 | `ApplicationRecord`, `Webhook::Delivery` |
| 非同期処理 | バックグラウンドタスク | `*Job`クラス群 |

### 5.3 データフロー

**典型的なリクエストフロー（カード作成）:**

```
1. ユーザー操作 (ブラウザ)
      │
      ▼
2. Turboがフォーム送信
      │
      ▼
3. routes.rb でルーティング
   POST /boards/:board_id/cards → CardsController#create
      │
      ▼
4. Controller が Model を呼び出し
   @board.cards.create!(card_params)
      │
      ▼
5. Model のコールバックが実行
   - before_save :set_default_title
   - after_create_commit :relay_later
      │
      ▼
6. Turbo Stream/HTML レスポンス
      │
      ▼
7. ブラウザが DOM を更新
```

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**Webリクエスト:**

```ruby
# ファイル: config/routes.rb:1-3
Rails.application.routes.draw do
  root "events#index"
```

**認証フロー:**

```ruby
# ファイル: app/controllers/concerns/authentication.rb:44-46
def require_authentication
  resume_session || authenticate_by_bearer_token || request_authentication
end
```

### 6.2 ビジネスロジック

**Cardモデル（中核エンティティ）:**

```ruby
# ファイル: app/models/card.rb:1-8
class Card < ApplicationRecord
  include Accessible, Assignable, Attachments, Broadcastable, Closeable, Colored, Commentable,
    Entropic, Eventable, Exportable, Golden, Mentions, Multistep, Pinnable, Postponable, Promptable,
    Readable, Searchable, Stallable, Statuses, Storage::Tracked, Taggable, Triageable, Watchable

  belongs_to :account, default: -> { board.account }
  belongs_to :board
  belongs_to :creator, class_name: "User", default: -> { Current.user }
```

**主要なConcernと機能:**
| Concern | 機能 |
|---------|------|
| `Eventable` | イベント追跡 |
| `Searchable` | 全文検索 |
| `Accessible` | アクセス制御 |
| `Commentable` | コメント機能 |
| `Taggable` | タグ付け |

### 6.3 データアクセス

**Active Record関連:**

```ruby
# ファイル: app/models/card.rb:22-27
scope :reverse_chronologically, -> { order created_at:     :desc, id: :desc }
scope :chronologically,         -> { order created_at:     :asc,  id: :asc  }
scope :latest,                  -> { order last_active_at: :desc, id: :desc }
scope :with_users,              -> { preload(creator: [ :avatar_attachment, :account ], assignees: [ :avatar_attachment, :account ]) }
scope :preloaded,               -> { with_users.preload(:column, :tags, :steps, :closure, :goldness, :activity_spike, :image_attachment, reactions: :reacter, board: [ :entropy, :columns ], not_now: [ :user ]).with_rich_text_description_and_embeds }
```

### 6.4 ユーティリティ/共通機能

**ビューヘルパー:**

```ruby
# ファイル: app/helpers/application_helper.rb:9-11
def icon_tag(name, **options)
  tag.span class: class_names("icon icon--#{name}", options.delete(:class)), "aria-hidden": true, **options
end
```

**JavaScript ヘルパー:**

```javascript
// ファイル: app/javascript/helpers/platform_helpers.js
export function isTouchDevice() { ... }
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Concern | 再利用可能なモジュール | 高 | `app/models/card/*.rb` |
| Scoped Controller | リソーススコープ設定 | 高 | `concerns/board_scoped.rb` |
| Current Attributes | リクエストスコープ状態 | 中 | `app/models/current.rb` |
| RESTful Resources | CRUD操作のリソース化 | 高 | `config/routes.rb` |

### 各パターンの詳細

#### パターン1: Concern（モジュール分割）

**目的:** 複数モデルで共有するロジックの分離

**実装例:**
```ruby
// ファイル: app/models/concerns/filterable.rb:1-17
module Filterable
  extend ActiveSupport::Concern

  included do
    has_and_belongs_to_many :filters

    after_update { filters.touch_all }
    before_destroy :remove_from_filters
  end

  private
    def remove_from_filters
      filters.each { it.resource_removed self }
    end
end
```

**解説:** `extend ActiveSupport::Concern`により、`included`ブロック内でクラスマクロ（`has_and_belongs_to_many`等）を呼び出せます。

#### パターン2: RESTfulリソース化

**目的:** アクションをCRUD操作として表現

**実装例（STYLE.mdより）:**
```ruby
// ファイル: config/routes.rb:76-103
resources :cards do
  scope module: :cards do
    resource :draft, only: :show
    resource :board
    resource :closure
    resource :column
    resource :goldness
    ...
  end
end
```

**解説:** `close`/`reopen`のようなカスタムアクションは`resource :closure`として新しいリソースを導入。

#### パターン3: Scopedコントローラー

**目的:** ネストされたリソースの親を自動設定

**実装例:**
```ruby
// ファイル: app/controllers/concerns/board_scoped.rb:1-18
module BoardScoped
  extend ActiveSupport::Concern

  included do
    before_action :set_board
  end

  private
    def set_board
      @board = Current.user.boards.find(params[:board_id])
    end

    def ensure_permission_to_admin_board
      unless Current.user.can_administer_board?(@board)
        head :forbidden
      end
    end
end
```

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定（routes.rb）
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: カード作成フロー

**概要:** ユーザーがボード内で新しいカードを作成する流れ

**処理フロー:**
```
routes.rb → CardsController#create → Card.create! → コールバック → レスポンス
```

**詳細な追跡:**

1. **ルーティング** (`config/routes.rb:45`)
   ```ruby
   resources :cards, only: :create
   ```

2. **コントローラー** (`app/controllers/cards_controller.rb:13-25`)
   ```ruby
   def create
     respond_to do |format|
       format.html do
         card = Current.user.draft_new_card_in(@board)
         redirect_to card_draft_path(card)
       end

       format.json do
         card = @board.cards.create! card_params.merge(creator: Current.user, status: "published")
         head :created, location: card_path(card, format: :json)
       end
     end
   end
   ```

3. **モデル保存時コールバック** (`app/models/card.rb:15-20`)
   ```ruby
   before_save :set_default_title, if: :published?
   before_create :assign_number

   after_save   -> { board.touch }, if: :published?
   after_touch  -> { board.touch }, if: :published?
   ```

4. **番号採番** (`app/models/card.rb:91-93`)
   ```ruby
   def assign_number
     self.number ||= account.increment!(:cards_count).cards_count
   end
   ```

#### 例2: 認証フロー

**概要:** ユーザーがログインする流れ

**処理フロー:**
```
SessionsController → Authentication concern → Session作成 → Cookie設定
```

**詳細な追跡:**

1. **認証チェック** (`app/controllers/concerns/authentication.rb:44-46`)
   ```ruby
   def require_authentication
     resume_session || authenticate_by_bearer_token || request_authentication
   end
   ```

2. **セッション復元** (`app/controllers/concerns/authentication.rb:48-52`)
   ```ruby
   def resume_session
     if session = find_session_by_cookie
       set_current_session session
     end
   end
   ```

3. **Current設定** (`app/models/current.rb:5-18`)
   ```ruby
   def session=(value)
     super(value)
     if value.present?
       self.identity = session.identity
     end
   end

   def identity=(identity)
     super(identity)
     if identity.present?
       self.user = identity.users.find_by(account: account)
     end
   end
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか（routes.rbを確認）
- [ ] 呼び出し関係を把握したか（Controller → Model → Concern）
- [ ] データの変換ポイントを確認したか（コールバック、scope）
- [ ] エラーハンドリングを確認したか（rescue, validation）
- [ ] 最終的な出力を確認したか（render, redirect, head）

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. README.md - プロジェクト概要
2. STYLE.md - コーディング規約
3. docs/code-to-docs/アーキテクチャ設計書/ - システム構成
4. docs/code-to-docs/機能一覧/ - 機能概要

#### 特定機能を理解したい場合
1. docs/code-to-docs/機能一覧/ - 対象機能の特定
2. docs/code-to-docs/機能設計書/{機能名}/ - 詳細設計
3. app/models/, app/controllers/ - 関連ソースコード

#### 改修作業を行う場合
1. 対象機能の設計書
2. config/routes.rb - URL設計確認
3. db/schema.rb - データ構造確認
4. test/ - 既存テストの確認

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| README.md | プロジェクト概要 | 最初に読む |
| STYLE.md | コーディング規約 | 実装前に確認 |
| docs/API.md | API仕様 | API開発時 |
| CONTRIBUTING.md | 貢献ガイド | PR作成前 |
| docs/development.md | 開発環境構築 | セットアップ時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `Current.user`はどこで設定されていますか？
A: `app/controllers/concerns/authentication.rb`の`set_current_session`メソッドで設定されます。`app/models/current.rb`の`session=`セッターが連鎖的に`identity`と`user`を設定します。

#### Q: Concernはどこに配置すべきですか？
A:
- 共有Concern: `app/models/concerns/`
- モデル固有Concern: `app/models/{model}/`
- コントローラーConcern: `app/controllers/concerns/`

#### Q: `!`付きメソッドと`!`なしメソッドの違いは？
A: STYLE.mdの規約により、`!`は対となる非破壊メソッドがある場合のみ使用します。例: `save`/`save!`, `update`/`update!`

### デバッグのヒント

1. **ルーティング確認**: `bin/rails routes | grep {resource}`
2. **コールバック追跡**: モデルの`before_*`, `after_*`を確認
3. **SQL確認**: `bin/rails console`で`ActiveRecord::Base.logger = Logger.new(STDOUT)`
4. **Turbo確認**: ブラウザのNetwork tabでTurbo Streamレスポンスを確認

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| Board | カードを整理するカンバンボード |
| Card | タスクやアイデアを表すカード |
| Column | ボード内のカラム（列） |
| Account | テナント（組織） |
| Identity | 認証用のユーザー識別子 |
| User | Account内でのユーザー表現 |
| Concern | 再利用可能なモジュール |
| Hotwire | Turbo + Stimulusのフレームワーク |
| Solid Queue | Railsのジョブキューシステム |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `app/models/card.rb` | Cardモデル | カードのビジネスロジック |
| `app/models/board.rb` | Boardモデル | ボードのビジネスロジック |
| `app/models/user.rb` | Userモデル | ユーザーのビジネスロジック |
| `app/models/current.rb` | Current Attributes | リクエストスコープ状態 |
| `app/controllers/cards_controller.rb` | カードコントローラー | カードCRUD処理 |
| `app/controllers/concerns/authentication.rb` | 認証Concern | 認証ロジック |
| `config/routes.rb` | ルーティング | URL設計 |
| `db/schema.rb` | DBスキーマ | テーブル定義 |

### C. 参考資料

- [Ruby on Rails ガイド](https://railsguides.jp/)
- [Hotwire公式ドキュメント](https://hotwired.dev/)
- [Stimulus Handbook](https://stimulus.hotwired.dev/handbook/introduction)
- プロジェクト内: STYLE.md - コーディング規約
- プロジェクト内: docs/API.md - API仕様
