【Rails】furimaアプリ　データベース設計

## 実装概要

1. フリーマーケットサイトを再現するために必要な、データベースの設計を行う。  
2. ER図を描画した後、READMEに設計情報を記述する。

以下の機能の実装条件を確認し、データベース設計を行うこと。

- ユーザー管理機能
- 商品出品機能
- 商品購入機能

## 1. フリーマーケットサイトを再現するために必要な、データベース設計を行う。

データベース設計の最初のステップは、アプリに必要な機能に基づいて各テーブルの構造を決めることです。ここでは、ユーザー情報、商品情報、購入履歴、配送先情報を管理する4つのテーブルを作成します。

### Usersテーブル
**目的**: ユーザーの情報を管理します。

**カラム説明**:
- **nickname**: ユーザーのニックネームを保存する（必須）
- **email**: ユーザーのメールアドレス（必須かつ一意制を持つ）
- **encrypted_password**: 暗号化されたパスワード（必須）
- **first_name**, **last_name**: ユーザーの名前を保存（必須）
- **first_name_kana**, **last_name_kana**: 名前のフリガナを保存（必須）
- **birth_date**: ユーザーの生年月日を保存（必須）

**リレーション**:
ユーザーは複数の商品を出品でき、複数の購入を行うため、`has_many :items` および `has_many :purchases` と関連付けます。

### Itemsテーブル
**目的**: 出品された商品の情報を管理します。

**カラム説明**:
- **name**: 商品の名前（必須）
- **description**: 商品の詳細説明（必須）
- **category_id**, **status_id**, **shipping_fee_id**, **prefecture_id**, **delivery_time_id**: 商品のカテゴリ、状態、配送料負担、発送元地域、発送までの日数に関する情報（必須）
- **price**: 商品の価格（必須）
- **user**: 出品者（外部キー）

**リレーション**:
商品は1人のユーザーに属し、購入履歴を持つため、`belongs_to :user` および `has_one :purchase` と関連付けます。

### Purchasesテーブル
**目的**: 商品の購入履歴を管理します。

**カラム説明**:
- **user**: 購入者の情報（外部キー）
- **item**: 購入された商品の情報（外部キー）

**リレーション**:
購入は1人のユーザーと1つの商品に紐付けられるため、`belongs_to :user` および `belongs_to :item` と関連付けます。また、購入履歴は配送先情報とも関連するため、`has_one :shipping_address` を持ちます。

### Shipping_addressesテーブル
**目的**: 購入された商品の配送先情報を管理します。

**カラム説明**:
- **postal_code**: 配送先の郵便番号（必須）
- **prefecture_id**: 配送先の都道府県（必須）
- **city**: 市区町村（必須）
- **address**: 番地（必須）
- **building_name**: 建物名（任意）
- **phone_number**: 電話番号（必須）
- **purchase**: 購入履歴（外部キー）

**リレーション**:
配送先は1つの購入履歴に関連付けられるため、`belongs_to :purchase` と関連付けます。

## 2. ER図を描画した後、READMEに設計情報を記述する

ER図を描くことで、各テーブル間のリレーションを視覚化し、データ構造を明確に整理します。描画後、その設計に基づいてREADMEファイルに以下の情報を記述します。

<今回の記事にはER図の添付は省略します＞

READMEには、各テーブルのカラム名やデータ型、制約（null制約や一意制）、さらにリレーションの詳細をまとめます。

```ruby:README.md
## Users テーブル

| Column             | Type    | Options                   |
|--------------------|---------|---------------------------|
| nickname           | string  | null: false               |
| email              | string  | null: false, unique: true |
| encrypted_password | string  | null: false               |
| first_name         | string  | null: false               |
| last_name          | string  | null: false               |
| first_name_kana    | string  | null: false               |
| last_name_kana     | string  | null: false               |
| birth_date         | date    | null: false               |

### Association
- has_many :items
- has_many :purchases

## Items テーブル

| Column             | Type       | Options                        |
|--------------------|------------|--------------------------------|
| name               | string     | null: false                    |
| description        | text       | null: false                    |
| category_id        | integer    | null: false                    |
| status_id          | integer    | null: false                    |
| shipping_fee_id    | integer    | null: false                    |
| prefecture_id      | integer    | null: false                    |
| delivery_time_id   | integer    | null: false                    |
| price              | integer    | null: false                    |
| user               | references | null: false, foreign_key: true |

### Association
- belongs_to :user
- has_one :purchase

## Purchases テーブル

| Column  | Type       | Options                        |
|---------|------------|--------------------------------|
| user    | references | null: false, foreign_key: true |
| item    | references | null: false, foreign_key: true |

### Association
- belongs_to :user
- belongs_to :item
- has_one :shipping_address

## Shipping_addresses テーブル

| Column        | Type       | Options                        |
|---------------|------------|--------------------------------|
| postal_code   | string     | null: false                    |
| prefecture_id | integer    | null: false                    |
| city          | string     | null: false                    |
| address       | string     | null: false                    |
| building_name | string     |                                |
| phone_number  | string     | null: false                    |
| purchase      | references | null: false, foreign_key: true |

### Association
- belongs_to :purchase
```
# 補足
## referencesタイプの外部キーで_idが不要な理由

Railsの`references`型を使用すると、デフォルトで外部キーを設定するため、カラム名に`_id`を追加する必要がありません。これはRailsが内部でこの命名規則を理解し、自動的に関連付けを行うためです。

例えば、`user`テーブルの`id`を参照するために、`user:references`と定義すると、Railsは自動的に`user_id`カラムを作成し、リレーションを正しく扱います。このため、`_id`を明示的に指定する必要がなく、コードがシンプルになります。

また、外部キー制約を持たせるためには、`foreign_key: true`オプションを追加することで、Railsが参照整合性を保つための適切な設定を行います。

このように、`references`型を使用することで、Railsは外部キーの命名と関連付けを効率的に処理し、開発者が手動で行う作業を減らすことができます。