[Rails] ECサイトのDB設計

#はじめに
Ruby on Rails(-v 5.2)を使用してECサイトを作成しました。今回はその際のDB設計についてこんな感じでやったよ、っていうのを書いていきます。

#参考にしたサイト
[若手プログラマー必読！５分で理解できるER図の書き方５ステップ](https://it-koala.com/entity-relationship-diagram-1897)


上記サイトの『システムシナリオを確認する』を参考にしていました。

以下の通り。

##ユースケース記述

- ユースケース名：顧客が商品を注文する
- 概要　　　　　：ECサイトで商品を注文する
- アクター　　　：顧客
- 事前条件　　　：ログインしている
- トリガー　　　：カートに商品をいれ、カート画面で”注文手続き”ボタンを押す
- 基本フロー
 - 注文画面で送付先、決済方法を入力する
 - 注文内容の確認”ボタンを押す
 - 注文内容を確認して、”注文確定”ボタンを押すと購入が完了する
- 備考　　　　　：”注文内容の確認”を押す際、入力をしていないと”注文内容の確認”ボタンを押せないようにする

##エンティティの洗い出し
- 顧客
- 商品
- 注文
- 決済
- 送付先住所

##マスタ系かトランザクション系か
- マスタ系
 - 顧客
 - 商品
- トランザクション系
 - 注文
 - 決済
 - 送付先住所

初期段階でここ位まで考えていましたが、作成に取りかかってからは適宜変更はしていました。
決済方法もクレジットカード(PAY.JPを使用)のみの決済にしています。

# 本題のDB設計
ECサイトでは必須機能であるカート機能のためのカートテーブル及び、注文の詳細テーブルをどうするべきか悩みましたが、以下のような感じで中間テーブルとして落とし込みました。

<img width="1003" alt="スクリーンショット 2020-06-01 23.28.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606031/ba3a8907-1d35-4f40-5ee1-ae75c5c71b3c.png">

カートテーブルに関しては、カートとしての役割でしかないのでカラムはPK以外ありません。
ユースケースでは記載していませんでしたが、ログインしていなくてもカート機能は使用したいので、user_id(FK)は持たせていません。

## users table
|Column|Type|Options|
|------|----|-------|
|nickname|string|null: false|
|email|string|default: "", null: false|
|password|string|null: false|
|encrypted_password|string|default: "", null: false|
|reset_password_token|string||
|reset_password_token|string||
|admin|boolean|default: false|
### Association
- has_many :comments, dependent: :destroy
- has_one :card, dependent: :destroy
- has_one :address, dependent: :destroy
- has_many :orders, dependent: :nullify

## orders table
|Column|Type|Options|
|------|----|-------|
|user|references|foreign_key: true|
|card|references|foreign_key: true|
|product|references|foreign_key: true|
|quantity|integer|null: false|
|status|integer|default: 0, null: false|
|postage|integer|default: 0, null: false|
|price|integer|null: false|
### Association
- belongs_to :user
- has_many :products, through: :order_details
- has_many :order_details, dependent: :destroy
- belongs_to :card
- belongs_to :address

## cards table
|Column|Type|Options|
|------|----|-------|
|customer_id|string|null: false|
|card_id|string|null: false|
|user_id|string|null: false|
### Association
- belongs_to :user
- has_one :order, dependent: :nullify

## addresses table
|Column|Type|Options|
|------|----|-------|
|destination_family_name|string|null: false|
|destination_first_name|string|null: false|
|destination_family_name_kana|string|null: false|
|destination_family_name_kana|string|null: false|
|postcode|integer|null: false|
|prefecture_code|string|null: false|
|address_city|string|null: false|
|address_street|string|null: false|
|address_building|string||
|phone_number|bigint||
|user|references|foreign_key: true, null: false|
### Association
- belongs_to :user
- has_one :order, dependent: :nullify

## brands table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## sexes table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## seasons table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## smell_impressions table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## smell_types table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## user_scenes table
|Column|Type|Options|
|------|----|-------|
|name|string||
### Association
has_many :products, dependent: :destroy

## products table
|Column|Type|Options|
|------|----|-------|
|name|string|null: false|
|namelap|string|null: false|
|description|text||
|image|text||
|price|integer||
|stock_quantity||
|brand|references|foreign_key: true|
|sex|references|foreign_key: true|
|season|references|foreign_key: true|
|smell_type|references|foreign_key: true|
|main_spice|references|foreign_key: true|
|smell_impression|references|foreign_key: true|
|use_scene|references|foreign_key: true|
### Association
- belongs_to :brand
- belongs_to :sex
- belongs_to :season, optional: true
- belongs_to :smell_type
- belongs_to :main_spice
- belongs_to :smell_impression
- belongs_to :use_scene
- has_many :comments, dependent: :destroy
- has_many :order_details
- has_many :orders, through: :order_details
- has_many :line_items, dependent: :destroy

## carts table
|Column|Type|Options|
|------|----|-------|
### Association
has_many :line_items, dependent: :destroy

## comments table
|Column|Type|Options|
|------|----|-------|
|user|references|foreign_key: true|
|product|references|foreign_key: true|
|text|text|null: false|
|rate|float|
### Association
belongs_to :product
belongs_to :user

## order_details table
|Column|Type|Options|
|------|----|-------|
|product|references|foreign_key: true|
|order|references|foreign_key: true|
|quantity|integer|null: false|
### Association
- belongs_to :order
- belongs_to :product

## line_items table
|Column|Type|Options|
|------|----|-------|
|product|references|foreign_key: true|
|cart|references|foreign_key: true|
|quantity|integer|default: 0, null: false|
### Association
- belongs_to :product
- belongs_to :cart