【Rails】データベース関連の知識、操作方法

#はじめに
Railsでアプリを開発するにあたって、データベース関連の設計、操作で色々苦労したので、自分の覚えの為にもまとめてみました。

#環境
- Ruby 2.5.1
- Rails 5.0.7

#そもそもデータベースとは
一定の形式で、「複数で共有、利用すること」と「検索、加工すること」を目的に整理されたデータの集まりの事を指す。プログラミングに限定された用語ではなく、日常生活で使う辞書等もデータベースみたいですね！

#データベース種類
- 階層型
- ネットワーク型
- リレーショナル型(RDBと呼ばれ最も主流)
 - Oracle Database
 - MySQL
 - PostgreSQL
 - Microsoft SQL Server　など
- NoSQL

MySQLを使って開発する事が多かったので、ここからMySQL(リレーショナル型)に絞って話を進めていきます。

#リレーショナルデータベース(RDB)、SQLとは
RDBは現在主流のデータベースで、エクセルみたいな表で構成されたデータベース。行と列を持ち、表形式でデータの関係性を示す。SQLを用いたデータのアクセスが可能。

SQL・・・Structured Query Languageの略で、リレーショナルデータベース（RDB）の操作を行うための言語。日本語訳は「構造化された問い合わせ言語」みたいな感じですかね！とにかくデータベースから情報を参照する言語。

#データベース設計で意識する事
正規化、アソシエーション、制約の話をまとめていきます。
##正規化
正規化・・・データベースのデータ構造をより効率的で重複や無駄のないシンプルな構造にするための手順。正規化の話は複雑ですが以下例です。
×予約情報が重複している為望ましくない
![UNADJUSTEDNONRAW_mini_1a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583732/92cb61a0-98b7-d46f-a311-c7e52a8de6bd.jpeg)
○テーブルを2つに分け予約情報の重複を解消
![2020-03-21 11.44のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583732/6e7515bd-5394-5452-02ec-c8b0f1c2aae2.jpeg)

##アソシエーション
アソシエーション・・・テーブル間の関係性をモデルの上の関係として操作できるようにする仕組み。
アソシエーションを利用すると複数のテーブルにまたがるデータ操作もより直感的に利用できる。
【モデルへの書き方】

```ruby:〇〇.rb
      # 1対多
      has_many :モデル名複数形
      # 多対1
      belongs_to :モデル名単数形
　　　 # 1対1 どちらかのモデルにhas_one,もう一方にbelongs_to
      has_one :モデル名単数形
      belongs_to :モデル名単数形
      # 多対多 中間テーブルが必要
      has_many :中間テーブル名複数形
　　　 has_many :モデル名複数形 through: :中間テーブル名複数形
```

##制約による安全性
制約とは・・・特定のデータの保存を許さない事。例えば同じニックネームのユーザーを登録できないようにする、名前のデータが空のユーザーを保存を許さない等。主な制約は以下です。
###制約種類
- NOT NULL制約・・・空(nil)レコードは保存できない。
- 一意性制約
・・・同じ値を設定できない。一意性制約をかけるときは、インデックスの作成も必要。
全てのデータを検索しないと、過去のデータと重複しているか判断できない為。
- 主キー制約
・・・Railsでは主キーはidカラムとして自動で作成(テーブルの一番左のカラム)。
- 外部キー制約
・・・外部キー制約は、外部キーの対応するレコードが必ず存在しなくてはいけないという制約です。外部キーのカラムに値があっても、その値を主キーとして持つ他のテーブルにレコードが存在する必要あり。

```ruby:create_users.rb
      # NOT NULL制約 nameはカラム名,stringはデータ型
      t.string :name, null: false
      # 一意性制約 インデックスとセット usersはテーブル名、emailはカラム名、stringはデータ型
      add_column :users, :email, :string
      add_index :users, :email, unique: true
      # 外部キー referencesはデータ型 これでuser_idというカラムが生成される
      t.references :user, foreign_key: true
```

#データ型種類
- string : 文字列
- text : 長い文字列
- integer : 整数
- float : 浮動小数(実数)
- datetime : 日時
- time : 時間
- date : 日付
- boolean : Boolean

#Railsでのコマンド集
```ruby:ターミナル/マイグレーションファイル
　 <データベース全般>
   #データベース作成(色んなテーブルを入れる箱の作成) database.ymlの内容に基づく
   rails db:create
   #データベース削除
   rails db:drop
   #マイグレーションファイルの適用
   rails db:migrate
   #マイグレーションファイルがどこまで適用されているか確認
   rails db:migrate:status
   #マイグレーションのバージョンを下げる デフォルトでは一つずつ
   rails db:rollback
   #マイグレーションのバージョンを複数下げる 例では3段階
   rails db:rollback STEP=3
 
   <モデル(テーブル)関連>コマンドでマイグレーションが作成されるので、そこで編集等を行う
   #モデル(テーブル作成) モデル名は単数形/頭文字を大文字にする
   rails g model モデル名

   #最初からカラム付きでモデルを作成したい時,2行目は例
   rails g model モデル名 カラム名：型
   rails g model User name:string email:string

   #既存のモデル(テーブル)にカラムを追加/削除,2行目は例
   rails g migration <マイグレーションファイル名> <追加するカラム名：型>
   rails g migration add_email_to_users email:string
   #以下マイグレーションファイル(add付きのファイル名でもカラムの削除は行える)
   # 追加(2行上のコマンドであればマイグレーション作成時からある)
   add_column :users, :email, :string
   # 削除(必要に応じて追加)
   remove_column :users, :gmail, :string
   # まとめて削除(必要に応じて追加)
   remove_columns :users, :column_1, :column_2 [, ...]
   # 追加する場所を指定する場合(必要に応じて追加)
   # 以下、nameカラムの直後にemailカラムを追加する場合
   add_column :users, :email, :string, :after => :name

   #指定のテーブル削除,2行目は例
   rails g migration Dropテーブル名
   rails g migration DropUser

   #既存のテーブル名を変更する,2行目は例
   rails g migration Rename変更前テーブル名To変更後テーブル名
   rails g migration RenameUserToCustomer

   #既存のカラムの内容を変更(例.Userモデルのemailカラムに制約をつける場合)
   rails g migration ChangeColumnToUser
   #以下マイグレーションファイル
　　# 変更内容
  　def up
    　change_column :users, :email, :string, null: false
  　end

  　# 変更前の状態
  　def down
    　change_column :users, :email, :string, null: true
  　end
```

#その他の便利なメソッド
外部キー制約が要因で特定のレコードを削除できないエラーが起きる事があると思います。その時はdelete, delete_all, destroy, destroy_allメソッドが大変便利です。

こちらの記事が大変参考になりました。
https://qiita.com/kamelo151515/items/0fa7fb15a1d2c1e44db2

#参考URL
https://qiita.com/kamelo151515/items/0fa7fb15a1d2c1e44db2
https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47