ActiveRecordで1対他の関連付けマイグレーションを作成する

# 目的
一つのテーブルに対して複数のテーブルを紐づけるモデルを作成する


# 環境
- ruby 2.0.0p481
- Rails 4.2

# 手順
## 前提
- 以下のモデルを作成する
COMPETITER
NEWS
ISSUE
ISSUE_MST

- 関連付け
 - COMPETITERは、複数のISSUE(論点)を持つ
 - COMPETITERは、複数のNEWS(ニュース)を持つ
 - ISSUEは一つのISSUE_MSTを持つ

## モデルの作成
### COMPETITORモデル
COMPETITORモデルは以下の定義とする

|項目 |物理名 | データ型| 
|:--|:---|:--|
| キー |id  |integer  |
|画像ファイル名 |img  |string  |
|所属団体名称 |party  |string  |

- rails generateコマンドで以下のように表現する

```
rails g model Competitor img:string name:string party:string
```

```
rails g model Competitor img:string name:string party:string
Warning: You're using Rubygems 2.0.14 with Spring. Upgrade to at least Rubygems 2.1.0 and run `gem pristine --all` for better startup performance.
Running via Spring preloader in process 22853
      invoke  active_record
      create    db/migrate/20160717072810_create_competitors.rb
      create    app/models/competitor.rb
      invoke    test_unit
      create      test/models/competitor_test.rb
      create      test/fixtures/competitors.yml
```


## 関連するモデルの作成
### NEWS_POSTSモデル
NEWS_POSTSモデルは以下の定義とする
1対多の関連付けを行う場合、多側のモデル名は複数形で定義する

|項目 |物理名 | データ型| 
|:--|:---|:--|
| キー |id  |integer  |
|画像ファイル名 |img  |string  |
|所属団体名称 |party  |string  |
|COMPETITORへの外部キー |competitor_id | references|

COMPETITORと異なるのは、外部キーを追加する必要がある点
その場合、references型のデータとして外部モデル名をモデル作成時に項目につかする

- rails generateコマンドで以下のように表現する

```
rails g model NewsPosts title:string link:string discription:text competitor:references
```

これだけで自動的にインデックスと外部参照キーのカラムが作成される
自動生成されるカラムは
参照先モデル名_id
となる

- 以下のようなマイグレーションファイルが作成される

```:マイグレーションファイル
class CreateNewsPosts < ActiveRecord::Migration
  def change
    create_table :news do |t|
      t.string :title
      t.string :link
      t.text :discription
      t.references :competitor, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end
```
外部キーがcompetitorへ作成されていることが確認できる

- モデル側を確認すると、多側の関連テーブルはbelongs_toが追加されている

```rb:news
class NewsPosts < ActiveRecord::Base
  belongs_to :competitor
end
```
- 関連される側のモデルに、has_manyを追加し、1対多の関連付けがモデルに指定される

```rb:competitor
class Competitor < ActiveRecord::Base
  has_many:news
end
```


### ISSUESモデル
ISSUESモデルは以下の定義とする

|項目 |物理名 | データ型| 
|:--|:---|:--|
| キー |id  |integer  |
|OK数|ok|integer|
|NG数|ng|integer|
|COMPETITORへの外部キー |competitor_id | references|
|ISSUE_MSTへの外部キー|issue_mst_id|references|

newsと同じように1対他の関連付けを指定する
今回の場合、ISSUE_MSTへも関連付けを持つ

```
rails g model issues ok:integer ng:integer competitor:references issue_mst:references
```

### ISSUES_MSTモデル
ISSUEは一つのISSUE_MSTを持つ

|項目 |物理名 | データ型| 
|:--|:---|:--|
| キー |id  |integer  |
| 論点名 | issue_name |string  |

```
rails g model IssueMst issue_name:string
```

## マイグレーションを実行する

```
bundle exec rake db:migrate
```

## 作成されたDBを確認する
WEBRickを起動したのち、以下のコマンドでDBコンソールを起動する

```
rails dbconsole
Warning: You're using Rubygems 2.0.14 with Spring. Upgrade to at least Rubygems 2.1.0 and run `gem pristine --all` for better startup performance.
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> 
```

sqliteで、作成したDBを確認できる

```sqlite3
sqlite> .tables
competitors        issues             schema_migrations
issue_msts         news    
```

```
sqlite> .schema
CREATE TABLE "schema_migrations" ("version" varchar NOT NULL);
CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");
CREATE TABLE "competitors" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "img" varchar, "name" varchar, "party" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE TABLE "news" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar, "link" varchar, "discription" text, "competitor_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE INDEX "index_news_on_competitor_id" ON "news" ("competitor_id");
CREATE TABLE "issue_msts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "issue_name" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE TABLE "issues" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "ok" integer, "ng" integer, "competitor_id" integer, "issue_mst_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE INDEX "index_issues_on_competitor_id" ON "issues" ("competitor_id");
CREATE INDEX "index_issues_on_issue_mst_id" ON "issues" ("issue_mst_id");
```

##　修正
### 誤って作成したモデルを削除したい

以下のモデルは誤って作成されたモデル

```
rails g model News title:string link:string discription:text
Warning: You're using Rubygems 2.0.14 with Spring. Upgrade to at least Rubygems 2.1.0 and run `gem pristine --all` for better startup performance.
Running via Spring preloader in process 22864
      invoke  active_record
      create    db/migrate/20160717073745_create_news.rb
      create    app/models/news.rb
      invoke    test_unit
      create      test/models/news_test.rb
      create      test/fixtures/news.yml
```

作りなおすため、いったん削除する
rails destroy model コマンドを使用する

```
rails destroy model News title:string link:string discription:text
Warning: You're using Rubygems 2.0.14 with Spring. Upgrade to at least Rubygems 2.1.0 and run `gem pristine --all` for better startup performance.
Running via Spring preloader in process 22889
      invoke  active_record
      remove    db/migrate/20160717073745_create_news.rb
      remove    app/models/news.rb
      invoke    test_unit
      remove      test/models/news_test.rb
      remove      test/fixtures/news.yml
```

# 参考文献
Railsガイド
Active Record マイグレーション
http://railsguides.jp/active_record_migrations.html