初心者がRailsガイドを1から100まで読んでみる　Railsをはじめよう編その14　もうひとつのモデルとの関連付け

###6.2番目のモデルを追加する

５章までで、Railsの基礎を学びました。
ルーティング、コントローラ、ビュー、フォームやリンクなどのビューヘルパー、モデル、CRUDの実装、などなど。
いろんな役者が出てきました。
６章では視点をちょびっとだけマクロにして、もうひとつモデルを作成し、既存のモデルと関連付けましょう。

####6.1.モデルを作成する
新たに作るモデルは、コメントです。
記事を書いてもそれが一方通行だと日記と一緒ですね。

じゃあ久しぶりのジェネレートコマンドを！

`$ rails generate model Comment commenter:string body:text article:references`

Articleモデルを作成した時にも出てきましたが、
このコマンドで、Commentって名前の、commenter(string型)、body(text型)を有するモデルを作成できる。

おっと、見慣れない`article:references`という文字が。
意味的にArticleモデルに関連するよーって感じに思える。

<img width="436" alt="スクリーンショット 2018-10-03 0.19.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/00d5923b-2888-a406-9965-f30513137b7b.png">


createされたファイルをみてみよう。
モデルをジェネレートした時は、マイグレーションファイルとモデル.rbができるんだったよね。
（テスト用のファイルとフィクスチャファイルもできるけど今は使わない）

中身はこうだ。

```タイムスタンプ_create_comments.rb
class CreateComments < ActiveRecord::Migration[5.1]
  def change
    create_table :comments do |t|
      t.string :commenter
      t.text :body
      t.references :article, foreign_key: true

      t.timestamps
    end
  end
end
```

```comment.rb
class Comment < ApplicationRecord
  belongs_to :article
end
```

マイグレーションファイル（上）にはコマンドで打ったテーブルの構造がなんとなく書いてあるのがわかる。
comment.rbには`belongs_to :article`と書いてあって、これもarticleモデルに関連している証拠っぽい。

「bashコマンドで使われている:referencesキーワードは、モデルの特殊なデータ型を表します。 これは、指定されたモデル名の後ろに_idを追加した名前を持つ新しいカラムをデータベーステーブルに作成します。マイグレーションの実行後にdb/schema.rbファイルを調べてみると理解が進みます。」
ふーん？

なんかよくわからないけど、articleモデルを作った時と同様にマイグレーションしてみよう
（これでマイグレーションファイルを元にテーブルが作られる、らしい）

`$ bin/rails db:migrate`
<img width="563" alt="スクリーンショット 2018-10-03 0.27.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/2e5a6982-0799-11ea-11ab-39b3affe9365.png">

####6.2.モデル同士を関連付ける

記事とコメントの関係ってどんなだろ？

「1つのコメントは1つの記事に属する (Each comment belongs to one article)。」
「1つの記事は複数のコメントを持てる (One article can have many comments)。」
このどっちかでしょう。

書いたコメントが別の記事と関連づいてたらカオスになりそう。

そういえばbelongs to articleってどこかで見たような…

```comment.rb
class Comment < ApplicationRecord
  belongs_to :article
end
```
ここだ！
これは「1つのコメントは1つの記事に属する (Each comment belongs to one article)。」を満たしているんだね。
一方のarticleの方はどうだろう。

```article.rb
class Article < ApplicationRecord
	validates :title, presence: true,
            		  length: { minimum: 5 }
end
```

バリデーションしかないよー。
こいつ自分のことしか考えてない。コメントちゃんのこと見向きもしていない状態だね。

ということで相思相愛にしてあげましょう。

```article.rb
class Article < ApplicationRecord
	has_many :comments
	validates :title, presence: true,
            		  length: { minimum: 5 }
end
```

```rb
	has_many :comments
```
が追加されました。
これは「1つの記事は複数のコメントを持てる (One article can have many comments)。」を表してますね。

こいつ…
スケコマシだな…

####6.3.コメントへのルーティングを追加する

モデルはつくった。
他にも準備するものがたくさんあるよね。
ルーティング、コントローラ、ビュー、etc

とりあえずルーティングの設定しちゃおうか。

```routes.rb
Rails.application.routes.draw do
    get 'welcome/index'

    resources :articles
  
    root 'welcome#index'
end
```
久しぶりに開いたroutes.rb
ここにコメントちゃんのためのルーティングを追加してあげよう。

```routes.rb
Rails.application.routes.draw do
  	get 'welcome/index'

  	resources :articles do
  		resources :comments
	end
  
  	root 'welcome#index'
end
```

なんと！
関連があるモデル同士にルーティングの関連付けもするにはこういう風にネスとして書くんだね。
これでどんな恩恵が受けられるんだろう。

ちなみにルーティングの設定はこんな感じになった。
（bin/rails routes　で確認できるよ）

<img width="687" alt="スクリーンショット 2018-10-03 0.43.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/648e9295-74ef-75ff-77c9-c7aa0210f413.png">
たくさん増えたね。

####6.4.コントローラを作成する

次はコントローラ！
ジェネレートコマンドでつくろう。

`$ rails generate controller Comments`

<img width="428" alt="スクリーンショット 2018-10-03 0.42.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/0f81cfdb-c29d-cc97-3530-d0dffcf8918c.png">

一旦ビューを修正しよう。
コメントはそれぞれの記事に対して書くものだ。
なので、index（一覧）でもnew（作成）でもedit（更新）でもなくshow画面につけるべきだよね。

```erb:show.html.erb
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>
 
<h2>Add a comment:</h2>
<%= form_with(model: [ @article, @article.comments.build ], local: true) do |form| %>
  <p>
    <%= form.label :commenter %><br>
    <%= form.text_field :commenter %>
  </p>
  <p>
    <%= form.label :body %><br>
    <%= form.text_area :body %>
  </p>
  <p>
    <%= form.submit %>
  </p>
<% end %>
 
<%= link_to 'Back', articles_path %>
| <%= link_to 'Edit', edit_article_path(@article) %>
```

こんな風にしました。
<img width="295" alt="スクリーンショット 2018-10-03 0.49.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/e0b57ccf-2ada-5b23-6de3-aa868b49d125.png">
こんな画面になります（見栄えはおいとこう）
コメントを送信するフォームが追加されてますね。
フォーム自体はnew.html.erbを作った時にも勉強した。
気になるのは

```erb
<%= form_with(model: [ @article, @article.comments.build ], local: true) do |form| %>
```
ここだなあ。
`@article.comments.build`ってなんだろう。
見た感じ、表示している@articleに関連するコメントを作っているように見えるけど。

今段階でコメントしてみると
<img width="277" alt="スクリーンショット 2018-10-03 0.54.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/a881e42e-3f0e-f31f-6780-ed8a3e02c708.png">

<img width="641" alt="スクリーンショット 2018-10-03 0.54.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/03b846ac-91e7-143d-24a6-459b059649d7.png">
あららアクションが見つからないって。そりゃそうだなにもコントローラいじってないもん。
ここで気にすべきは、コメントコントローラのcreateアクションにリクエストを送信していること。
あの↑の書き方でそういう風にリクエストが飛ぶのかあ。
（フォームどのアクションにリクエスト送信するのか知る術ってないのかなあ。調べよう）

それじゃあコメントコントローラのcreateアクションを実装してあげましょうか。

```comments_controller.rb
class CommentsController < ApplicationController
	def create
    	@article = Article.find(params[:article_id])
    	@comment = @article.comments.create(comment_params)
    	redirect_to article_path(@article)
  	end
 
    private
    	def comment_params
      		params.require(:comment).permit(:commenter, :body)
    	end
end
```

こうなりました。
パラメータのidでArticleモデルからfindして

```rb
    	@comment = @article.comments.create(comment_params)
```
ここでコメントを作成（モデルに登録）しているのかな。
こんな書き方するのかあ。

その後、article_path(@article)にリダイレクトしている。
これは以前も出てきた書き方だ。ルーティングを確認すると、article_pathはshowアクションだ。

comment_paramsはstrong parameter避けって習ったね。

登録したコメントをもってshowアクションにリダイレクトされるのでもうちょっと改造しよう。

```erb:show.html.erb
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>
 
<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>Commenter:</strong>
    <%= comment.commenter %>
  </p>
 
  <p>
    <strong>Comment:</strong>
    <%= comment.body %>
  </p>
<% end %>
 
<h2>Add a comment:</h2>
<%= form_with(model: [ @article, @article.comments.build ], local: true) do |form| %>
  <p>
    <%= form.label :commenter %><br>
    <%= form.text_field :commenter %>
  </p>
  <p>
    <%= form.label :body %><br>
    <%= form.text_area :body %>
  </p>
  <p>
    <%= form.submit %>
  </p>
<% end %>
 
<%= link_to 'Edit Article', edit_article_path(@article) %> |
<%= link_to 'Back to Articles', articles_path %>
```

```erb
<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>Commenter:</strong>
    <%= comment.commenter %>
  </p>
 
  <p>
    <strong>Comment:</strong>
    <%= comment.body %>
  </p>
<% end %>
```
ここを追加した。
これは登録されているコメントを表示しているね。

みてみよう。
<img width="306" alt="スクリーンショット 2018-10-03 1.05.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/1a204f96-a55d-f06f-64e5-79c205e4fb06.png">

コメントの分だけ表示された！

#参考
Railsガイド
https://railsguides.jp/getting_started.html