データベーステーブルの作成

# やること
* データベーススケルトンの生成
```terminal:データベーススケルトンの生成
$ rails g model your-app
```
* マイグレーションスクリプトの編集（カラム・型の定義）
```terminal:マイグレーションスクリプトの編集
$ vim db/migrate/20230101000000_create_xxxxx.rb
```
* マイグレーションの実行
```terminal:マイグレーションの実行
$ rails db:migrate
```
* 生成したモデルにpassword暗号化などのメソッドを追加する
```terminal:models/class_name.rb
$ vim models/class_name.rb
```

* seedデータの作成
```terminal:必要に応じてseedスクリプトを作成
$ vim db/seeds.rb        # 実行するクエリを作成
```
 ※場合によっては作り直しのために、以下のリセットを実行する
```terminal:データベースのリセット
$ rails db:reset
```

* RSpec（specファイルの作成）
```terminal:rspecでテストの実行
$ vim spec/models/xxxxxx_spec.rb
```
* テストファイルの実行
```terminal:rspecでテストの実行
$ rspec spec/models/xxxxxx_spec.rb
```
* ルーティングの追加
* controllerの生成


# データベーステーブルの作成

## スケルトンの生成
Railsプロジェクトを作成した後は、データベーステーブルの作成、モデルクラスの作成をします。
Dockerを使用している場合は、Webコンテナにログインして実行します。
```terminal:スケルトンの生成
$ cd your-app
$ bin/rails g model StaffMember
```
rails g modelコマンドでモデルに関連するスケルトンを作成します。
このコマンドによって以下のファイルが生成されます。

* db/migrate/20230101000000_create_staff_members.rb（マイグレーションスクリプト） 
 データベースのスキーマを変更するRubyスクリプト。テーブルを追加したり、定義を変更する役割。
* app/models/staff_member.rb（モデルファイル）
 ここでは、StaffMemberクラスを定義するファイル
* spec/models/staff_member_spec.rb（RSpec用のspecファイル）
　StaffMemberクラスのためのspecファイル

もし、前述のコマンドでスペル等を間違って実行してしまった場合は、次のコマンドで上記のスケルトンを削除してやり直しできる。

```terminal:destroyコマンド
$ bin/rails destroy model <削除したいモデル名>
```

## マイグレーションスクリプト

マイグレーションスクリプトのインスタンスメソッドchangeの中でデータベースにテーブルを追加する手順を記述します。
#### マイグレーションスクリプトのデフォルト値
```rb:db:migrate/20230101000000_create_staff_members.rb
1 class CreateStaffMembers < ActiveRecord::Migration[6.0]
2   def change
3     create_table :staff_members do |t|
4 
5       t.timestamps
6     end
7   end
8 end
```
:::note info
create_tableメソッド・・・引数に指定した名前のテーブルを作成する
ブロックの中・・・そのテーブルが持つべきカラムの型や名前を記述する
:::

### マイグレーションスクリプトの作成例
ファイルを編集して、自分のデータベーステーブルに必要なレコードの定義を書きます。

```rb:db:migrate/20230101000000_create_staff_members.rb
1  class CreateStaffMembers < ActiveRecord::Migration[6.0]
2    def change
3      create_table :staff_members do |t|
4        t.string :email, null: false # メールアドレス
5        t.string :family_name, null: false # 姓
6        t.string :given_name, null: false # 名
7        t.string :family_name_kana, null: false # 姓（カナ）
8        t.string :given_name_kana, null: false # 名（カナ）
9        t.string :hashed_password # パスワード
10       t.date :start_date, null: false # 開始日
11       t.date :end_date # 終了日
12       t.boolean :suspended, null: false, default: false # 無効フラグ
13 
14       t.timestamps
15     end
16
17     add_index :staff_members, "LOWER(email)", unique: true
18     add_index :staff_members, [ :family_name_kana, :given_name_kana ]
19   end
20 end
```
:::note info
解説
* NOT NULL制約
オプションnullにfalseを指定すると、このカラムにNOT NULL制約を設定します。
この制約が課せられたカラムにNULL値をセットしようとするとPostgreSQL側でエラーになります。

* UNIQUE制約（一意性制約）
同じメールアドレスを持つユーザーが誤って登録されることがなくなります。 

* カラム型ごとの専用メソッド
利用できるメソッドやオプションの一覧は以下のサイトで調べます。
[Ruby on RailsのAPI検索サイト](https://api.rubyonrails.org)

* インデックス（索引）の設定
マイグレーションスクリプトの17行目で、カラムemailに対するインデックスを記述しています。
カラムにインデックスを作成する目的は、そのカラムを用いた検索やソートの高速化です。

      書き方
      add_index :table_name, "column_name"

* 複合インデックス
    18行目では、カラム（family_name_kana）と（given_name_kana）に複合インデックスを設定しています。

      add_index :staff_members, [ :family_name_kana, :given_name_kana ]
 
　　　※ユーザ一覧をフリガナでソートして表示する時に、この複合インデックスが効果を発揮します。
:::

:::note alert
インデックスはむやみに作らない（効果的な使い所を考える）
インデックスを管理するためのメモリやディスクスペースが余分に必要になるため、
テーブルへの書き込み時にインデックスを書き換えるために付加的な処理が必要になる。
むやみにインデックスを作成すれば良いというものではない。
:::

### マイグレーションの実行
* マイグレーションスクリプトの適用
マイグレーションスクリプトを作成したので以下のコマンドでデータベースに適用させる。
```terminal:マイグレーション
$ bin/rails db:migrate
```
:::note info
マイグレーションを実行すると...
db/schema.rbが生成される。
このファイルには、データベースの構造を復元するための情報が記述される。
:::

* マイグレーションエラーが発生した場合
マイグレーションスクリプトを見直した上で次のコマンドを実行する
```terminal:マイグレーションのリセット
$ bin/rails db:migrate:reset
```
このコマンドは、いったんデータベースを削除した上で新たにデータベースを作成してマイグレーションを実行する。