# 機能設計書 1-Active Support

## 概要

本ドキュメントは、Ruby on RailsフレームワークにおけるActive Supportライブラリの機能設計を記述する。Active Supportは、Rubyコア拡張とRails全体で利用される汎用的なサポートライブラリを提供するツールキットである。

### 本機能の処理概要

Active Supportは、Rubyの標準ライブラリを拡張し、Railsアプリケーション開発に必要な基盤機能を提供するコアライブラリである。

**業務上の目的・背景**：Rubyの標準ライブラリだけでは、大規模なWebアプリケーション開発において冗長なコードが必要となる。Active Supportは、開発者が繰り返し必要とする共通処理をメソッドとして提供し、コードの可読性向上、開発効率の向上、および保守性の改善を実現する。また、マルチバイト文字列処理、タイムゾーン対応、国際化など、グローバルなWebアプリケーション開発に必須の機能を標準化している。

**機能の利用シーン**：
- String、Array、Hash、Numeric等のRubyコアクラスに対するメソッド拡張が必要な場面
- タイムゾーンを考慮した日時処理が必要な場面
- キャッシュ機構を利用したパフォーマンス最適化
- コールバック機構によるオブジェクトライフサイクル管理
- 国際化・多言語対応（I18n）
- メッセージの暗号化・署名・検証

**主要な処理内容**：
1. Rubyコアクラス（String、Array、Hash、Numeric、Object等）への拡張メソッド追加
2. TimeWithZoneによるタイムゾーン対応の日時処理
3. Cache::Store系クラスによるキャッシュ機構の提供
4. Callbacksモジュールによるコールバック機構の提供
5. Concernモジュールによるモジュールミックスインの簡素化
6. Multibyte::Unicodeによるマルチバイト文字列処理
7. MessageEncryptor/MessageVerifierによるメッセージの暗号化・署名
8. Inflectorによる単語の単数形・複数形変換

**関連システム・外部連携**：
- I18n gem: 国際化・多言語対応
- TZInfo gem: タイムゾーン情報の取得
- Redis/Memcached: キャッシュバックエンド
- 各種キューイングバックエンド（Active Jobと連携）

**権限による制御**：Active Supportは基盤ライブラリであり、認可・認証レベルでの制御は行わない。ただし、MessageEncryptor/MessageVerifierを使用した暗号化機能は、適切な鍵管理が前提となる。

## 関連画面

Active Supportは基盤ライブラリであり、特定の画面には直接対応しない。Rails全体の基盤として機能する。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面共通 | 基盤機能 | すべてのRails機能がActive Supportに依存 |

## 機能種別

基盤ライブラリ / ユーティリティ / コア拡張

## 入力仕様

### 入力パラメータ

Active Supportは多数のモジュール・クラスで構成されるため、代表的なAPIの入力仕様を示す。

#### TimeWithZone

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| utc_time | Time | Yes（local_timeがnilの場合） | UTC時刻 | 有効なTimeオブジェクト |
| time_zone | TimeZone | Yes | タイムゾーンオブジェクト | 有効なTimeZoneオブジェクト |
| local_time | Time | No | ローカル時刻 | 有効なTimeオブジェクト |
| period | TZInfo::TimezonePeriod | No | タイムゾーン期間 | - |

#### Cache::Store#fetch

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String/Array | Yes | キャッシュキー | - |
| options | Hash | No | オプション（expires_in等） | - |
| block | Block | No | キャッシュミス時の処理ブロック | - |

#### MessageEncryptor#encrypt_and_sign

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | Object | Yes | 暗号化対象の値 | - |
| options | Hash | No | 有効期限等のオプション | - |

### 入力データソース

- アプリケーションコードからの直接呼び出し
- Rails設定ファイル（config/application.rb等）
- 環境変数
- I18n翻訳ファイル（config/locales/*.yml）

## 出力仕様

### 出力データ

#### TimeWithZone

| 項目名 | 型 | 説明 |
|--------|-----|------|
| time | Time | ローカル時刻 |
| utc | Time | UTC時刻 |
| zone | String | タイムゾーン略称 |
| utc_offset | Integer | UTCからのオフセット（秒） |

#### Cache::Store#fetch

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cached_value | Object | キャッシュされた値またはブロックの実行結果 |

#### MessageEncryptor

| 項目名 | 型 | 説明 |
|--------|-----|------|
| encrypted_message | String | 暗号化・署名されたメッセージ（Base64エンコード） |

### 出力先

- メモリ上のオブジェクト
- キャッシュストア（ファイル、Redis、Memcached等）
- ログファイル（Loggerを使用時）

## 処理フロー

### 処理シーケンス

```
1. Active Supportのロード
   └─ require "active_support" により、autoload定義が読み込まれる
2. 各モジュールの遅延ロード
   └─ 実際に使用されるタイミングでautoloadされる
3. コア拡張の適用
   └─ require "active_support/core_ext" により、Rubyコアクラスが拡張される
4. 各機能の利用
   └─ アプリケーションコードから各種ユーティリティを呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[ActiveSupport読込] --> B{Autoload定義}
    B --> C[Concern]
    B --> D[Callbacks]
    B --> E[Cache]
    B --> F[TimeWithZone]
    B --> G[MessageEncryptor]
    B --> H[その他モジュール]

    C --> I[モジュールミックスイン処理]
    D --> J[コールバック定義・実行]
    E --> K[キャッシュ読み書き]
    F --> L[タイムゾーン変換]
    G --> M[暗号化・復号]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | キャッシュ有効期限 | expires_in で指定された期間が経過したキャッシュエントリは無効となる | キャッシュアクセス時 |
| BR-002 | タイムゾーン変換 | Time.zone が設定されている場合、日時オブジェクトはそのタイムゾーンで解釈される | 日時処理時 |
| BR-003 | メッセージ有効期限 | expires_in/expires_at で指定された期限を過ぎたメッセージは復号・検証に失敗する | メッセージ復号時 |
| BR-004 | コールバック実行順序 | before -> around -> after の順でコールバックが実行される | run_callbacks 呼び出し時 |

### 計算ロジック

**キャッシュ有効期限計算**：
```ruby
expires_at = Time.now.utc + expires_in
entry_expired = entry.expires_at && Time.now.utc >= entry.expires_at
```

**タイムゾーンオフセット計算**：
```ruby
utc_offset = period.observed_utc_offset  # 秒単位
```

## データベース操作仕様

Active Supportは直接データベース操作を行わない。ただし、Cache::Store の一部実装（例：ActiveSupport::Cache::RedisCacheStore）は外部ストレージに対してデータの読み書きを行う。

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | Active Support自体はDB操作を行わない |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ActiveSupport::MessageVerifier::InvalidSignature | メッセージの署名検証に失敗 | メッセージの改ざんまたは鍵の不一致を確認 |
| - | ActiveSupport::MessageEncryptor::InvalidMessage | メッセージの復号に失敗 | 暗号化鍵の一致を確認 |
| - | ActiveSupport::Cache::DeserializationError | キャッシュのデシリアライズに失敗 | キャッシュフォーマットの互換性を確認 |
| - | Encoding::InvalidByteSequenceError | 不正なバイトシーケンス | 入力文字列のエンコーディングを確認 |

### リトライ仕様

キャッシュ操作においてバックエンド接続エラーが発生した場合、RedisCacheStore等では設定に応じてリトライが行われる。デフォルトではリトライは行われず、例外がそのまま伝播する。

## トランザクション仕様

Active Supportはトランザクション管理を直接行わない。ただし、`ActiveRecord.after_all_transactions_commit` などのコールバック連携機能を提供する。

## パフォーマンス要件

- キャッシュ読み込み: 1ms以下（MemoryStore使用時）
- 文字列変換処理: マイクロ秒オーダー
- 暗号化・復号: データサイズに比例（AES-256-GCM使用）

## セキュリティ考慮事項

- MessageEncryptor/MessageVerifierは適切な鍵管理が前提
- シークレットキーは環境変数またはcredentialsで管理
- YAML安全なロード（psych/safe_load）の使用を推奨
- 暗号化アルゴリズムはAES-256-GCMがデフォルト

## 備考

Active Supportは `activesupport` gemとして提供され、Rails以外のRubyプロジェクトでも単独で利用可能。

---

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

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、Active Supportの全体構造とオートロード定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | active_support.rb | `activesupport/lib/active_support.rb` | モジュール定義とautoload一覧を確認。どのようなモジュールが利用可能か把握する |

**読解のコツ**: `autoload` と `eager_autoload` の違いに注目。eager_autoloadブロック内のモジュールは起動時にロードされる。

**主要処理フロー**:
- **36-93行目**: ActiveSupportモジュールの定義とautoload宣言
- **99-103行目**: eager_load!メソッドによる積極的ロード処理
- **109-113行目**: error_reporter、event_reporterのシングルトンインスタンス設定

#### Step 2: エントリーポイントを理解する

Active Supportは通常 `require "active_support"` または `require "active_support/all"` で読み込まれる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | active_support.rb | `activesupport/lib/active_support.rb` | モジュール定義とグローバル設定 |
| 2-2 | all.rb | `activesupport/lib/active_support/all.rb` | 全機能読み込み時のエントリーポイント |

#### Step 3: コア拡張を理解する

Rubyコアクラスへの拡張メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | string/multibyte.rb | `activesupport/lib/active_support/core_ext/string/multibyte.rb` | String#is_utf8? メソッドの実装 |
| 3-2 | multibyte.rb | `activesupport/lib/active_support/multibyte.rb` | マルチバイト処理モジュールの定義 |

**主要処理フロー（string/multibyte.rb）**:
- **11-20行目**: is_utf8?メソッドの実装。エンコーディングに応じたUTF-8判定ロジック

#### Step 4: TimeWithZoneを理解する

タイムゾーン対応の日時処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | time_with_zone.rb | `activesupport/lib/active_support/time_with_zone.rb` | TimeWithZoneクラスの主要メソッド |

**主要処理フロー**:
- **51-61行目**: initialize メソッド。utc_time、time_zone、local_timeの初期化
- **64-66行目**: time メソッド。UTCからローカル時刻への変換
- **69-71行目**: utc メソッド。ローカル時刻からUTCへの変換

#### Step 5: キャッシュ機構を理解する

キャッシュストアの抽象化と実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | cache.rb | `activesupport/lib/active_support/cache.rb` | Cache::Storeの基本定義とlookup_store |

**主要処理フロー（cache.rb）**:
- **17-22行目**: 各種CacheStoreのautoload定義
- **87-99行目**: lookup_storeメソッド。シンボルから適切なCacheStoreクラスを解決

#### Step 6: コールバック機構を理解する

コールバックの定義と実行フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | callbacks.rb | `activesupport/lib/active_support/callbacks.rb` | Callbacksモジュールの実装 |

**主要処理フロー**:
- **65-71行目**: includedブロック。クラス属性__callbacksの初期化
- **97-100行目**: run_callbacksメソッドの開始。コールバックチェーンの取得と実行

### プログラム呼び出し階層図

```
ActiveSupport (module)
    │
    ├─ Dependencies (autoload)
    │      └─ Autoload機構の実装
    │
    ├─ Callbacks (module)
    │      ├─ define_callbacks (ClassMethods)
    │      ├─ set_callback (ClassMethods)
    │      └─ run_callbacks (InstanceMethods)
    │
    ├─ Cache (module)
    │      ├─ lookup_store
    │      └─ Store (class)
    │             ├─ fetch
    │             ├─ read
    │             ├─ write
    │             └─ delete
    │
    ├─ TimeWithZone (class)
    │      ├─ time
    │      ├─ utc
    │      └─ in_time_zone
    │
    └─ MessageEncryptor/MessageVerifier
           ├─ encrypt_and_sign
           └─ decrypt_and_verify
```

### データフロー図

```
[入力]                    [処理]                           [出力]

Rubyコアオブジェクト ───▶ core_ext拡張メソッド ───▶ 拡張されたオブジェクト
       String
       Array
       Hash
       etc.

Time + TimeZone ───▶ TimeWithZone ───▶ ローカル時刻/UTC時刻
                          │
                          └─ TZInfo::TimezonePeriod

キャッシュキー + 値 ───▶ Cache::Store ───▶ キャッシュストレージ
                             │              (Memory/File/Redis/Memcached)
                             └─ Coder (シリアライズ)

平文 + 秘密鍵 ───▶ MessageEncryptor ───▶ 暗号文（Base64）
                        │
                        └─ OpenSSL::Cipher (AES-256-GCM)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| active_support.rb | `activesupport/lib/active_support.rb` | ソース | メインエントリーポイント、autoload定義 |
| callbacks.rb | `activesupport/lib/active_support/callbacks.rb` | ソース | コールバック機構の実装 |
| cache.rb | `activesupport/lib/active_support/cache.rb` | ソース | キャッシュストア抽象化 |
| time_with_zone.rb | `activesupport/lib/active_support/time_with_zone.rb` | ソース | タイムゾーン対応日時クラス |
| message_encryptor.rb | `activesupport/lib/active_support/message_encryptor.rb` | ソース | メッセージ暗号化 |
| message_verifier.rb | `activesupport/lib/active_support/message_verifier.rb` | ソース | メッセージ署名・検証 |
| concern.rb | `activesupport/lib/active_support/concern.rb` | ソース | モジュールミックスイン簡素化 |
| inflector.rb | `activesupport/lib/active_support/inflector.rb` | ソース | 単語変換（単数形/複数形等） |
| multibyte.rb | `activesupport/lib/active_support/multibyte.rb` | ソース | マルチバイト文字列処理 |
| core_ext/ | `activesupport/lib/active_support/core_ext/` | ディレクトリ | Rubyコアクラス拡張群 |
