Dockerを使用したRails開発③(モデルとテーブル作成)

# やること
今回は、アノテーション付きのモデル作成とテーブル作成までを行いたいと思います。

やることは以下の通り
1. GEM(annotate)の追加
2. ジェネレータコマンドでモデル作成
3. マイグレーションコマンドでテーブル作成
4. シードで初期レコード追加

# GEM(annotate)の追加
annotateというGEMを追加してマイグレートされる度に自動的にモデルにテーブル構造がアノテーションとして付与されるよう設定を行おうと思います。

まずは、Gemfileにannotateを追加します。

```ruby:Gemfile
group :development, :test do
  # 〜関係ないとこは省略
  gem 'annotate'
end
```

今回は開発環境(development)とテスト環境(test)へのみインストールするため、
group :development, :test doの中に記載します。

あとは`docker-compose build`すればGemインストール完了

次にマイグレートする度に自動でテーブル構造を書き出すよう以下のコマンドを実行します。
`docker-compose run web rails g annotate:install`

コンテナでコマンド実行する際に
`docker-compose run 〜`と`docker-compose exec 〜`の
２通りの方法がありますが、調べてみると・・・
run：コンテナ起動してコマンド実行
exec：起動中のコンテナでコマンド実行
の違いがあるそうです。

試しにコンテナを起動していない状態でexecしたら以下のエラーになりました。
コンテナが見つかりませんとのこと。

```
ERROR: No container found for web_1
```

# ジェネレータコマンドでモデル作成

ジェネレーターコマンドを実行してモデルファイルを作成しようと思います。
実行コマンドはこんな感じ(コンテナ起動済みなのでexecで！)

`docker-compose exec web rails g model bike name:string`

`rails g model 'テーブル名' 'カラム名:型' 'カラム名:型'・・・` で
モデルファイルとマイグレーションファイルが作成されます。

今回は文字列型のnameというカラムを持ったbikeテーブルを作成します。
ちなみにidはPKとして自動作成されるのでカラムとしての指定は不要です。

マイグレーションファイル内のCREATE文ではテーブル名が複数形(〜s)の形で作成されるので、実際のテーブルはbikesという名前になります。

次にsrc/app/models/下にモデルファイルが作成されているので、中身を確認してみます。

```ruby:bike.rb
class Bike < ApplicationRecord
end
```

この時点ではアノテーションの付与はまだ行われていません。

src/db/migrate下にマイグレーションファイルが作成されたので、こちらも中身を確認してきます。

```ruby:20180924030558_create_bikes.rb
class CreateBikes < ActiveRecord::Migration[5.2]
  def change
    create_table :bikes do |t|
      t.string :name

      t.timestamps
    end
  end
end
```

テーブル作成用のCREATE文が作成されていることがわかります。
t.timestampsはテーブルへ作成日と更新日のカラムを追加してくれるので、このままにしておきます。

あとsrc/test配下にテスト用のファイルが出力されていましたが、これはおいおい勉強していこうと思います。。今回は割愛。

# マイグレーションコマンドでテーブル作成

`docker-compose exec web rake db:migrate`を実行し、テーブル登録を行います。

実行後にモデルファイルの中身を再度確認してみます。

```ruby:bike.rb
# == Schema Information
#
# Table name: bikes
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Bike < ApplicationRecord
end
```

するとアノテーションが付与されていることがわかります。

次に以下のコマンドを実行してMySQLへ接続してテーブルが登録されているかを確認します。
`docker-compose exec db mysql -u root -p` 実行後、パスワードを入力してMySQLへ接続
 
ここからはMySQLのコマンドでの操作になります。

`use app_development;` で使用するデータベースを選択
マイグレートするとデフォルトでxxxxx_developmentのデータベースに登録されるようです。

`show tables;` でbikesテーブルが正しく登録されていることがわかります。

```
+---------------------------+
| Tables_in_app_development |
+---------------------------+
| ar_internal_metadata      |
| bikes                     |
| schema_migrations         |
+---------------------------+
3 rows in set (0.00 sec)
```

`DESC bikes;` で定義情報が先ほどアノテーションとして付与されていたものと同じであることが確認できます。

```
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
```

`docker-compose exec web rake db:migrate`は、実行していないマイグレーションファイルを実行してくれるため、この状態で再度実行すると以下のように変更する内容がないと言われます。

```
Model files unchanged.
```

試しに`docker-compose exec web rake db:rollback` で直前の動作(bikesテーブルの追加)を取り消すと再びmigrateができることが確認できました。

# シードで初期レコード追加

シードと呼ばれる初期データ投入用の機能を利用してbikesテーブルにレコード追加してみようと思います。

src/db/seeds.rbに以下を追加します。

```ruby:seeds.rb
# bikesテーブルにレコード追加
Bike.create(
	[{ name: 'CB250F'}, 
	 { name: 'AX-1'}, 
	 { name: 'CB350'}, 
	 { name: 'FMX650'}, 
	 { name: 'CB1000R'}]
)
```

BikeモデルがApplicationRecordクラスを継承し、
ApplicationRecordクラスがO/Rマッパーの機能を備えたActiveRecordクラスを継承しているため、これだけでテーブルへレコード追加ができます。

あとは`docker-compose exec web rake db:seed`を実行するだけ

テーブルの中身を確認すると

```
+----+---------+---------------------+---------------------+
| id | name    | created_at          | updated_at          |
+----+---------+---------------------+---------------------+
|  1 | CB250F  | 2018-09-24 06:11:19 | 2018-09-24 06:11:19 |
|  2 | AX-1    | 2018-09-24 06:11:19 | 2018-09-24 06:11:19 |
|  3 | CB350   | 2018-09-24 06:11:19 | 2018-09-24 06:11:19 |
|  4 | FMX650  | 2018-09-24 06:11:19 | 2018-09-24 06:11:19 |
|  5 | CB1000R | 2018-09-24 06:11:19 | 2018-09-24 06:11:19 |
+----+---------+---------------------+---------------------+
5 rows in set (0.01 sec)

```

レコード登録が行われていることが確認できます！
HONDAの車種ばっか笑

今日はここまで！
次の記事でテーブル同士の関連付けについてまとめていこうと思います。