【Rails初心者】コメント機能追加まとめ

## _【Rails初心者】コメント機能追加まとめ_
コメント機能を追加する方法を自分なりにまとめてみた…

## コメント機能とは？
 投稿された画像に対して、コメントをつけることができる機能
・コメント欄には、意見や返答を書き込める
・書き込まれたコメントは、更新日時が新しいコメントが、上から順に表示される

[サイボウズ Office マニュアル](https://jp.cybozu.help/o/ja/user/app/ms/basic/comment.html) がイメージをつかみやすかったです
_※マニュアル系は自分が、今後機能を盛り込むときの参考資料として使えそう！！_

## 必要なこと
- コメント機能に必要な DBの追加
- モデル作成
- モデルに関連付けを追加
- Routing編集
- コントローラを作成
- View編集


## コメント機能を作成
### 1.コメント機能に必要なDBを確認する

| カラム名 | データ型 | カラムの説明 |
| :---: | :---: | :---: |
| id | integer | コメントごとのID |
| comment | text | コメント本文 |
| user_id | integer | コメントしたユーザのID |
| post_id | integer | コメントされた投稿画像のID |


### 2.以下のコマンドで、コメント機能に必要なDBを追加
~~~:Console  PostComment DB/Model の作成
#id created_at updated_at は自動で再生されるため記載はいらない
username:~/environment/hoge $ rails g model PostComment comment:text user_id:integer post_id:integer
~~~

マイグレーションでテーブルをデータベースへ反映させます。
~~~:Console
username:~/environment/hoge $ rails db:migrate
~~~

### 3.PostCommentModelにAssociationを追加
PostCommentModel が UserModel と PostMdelに属していることをcomment.rbに記載

~~~ruby:app/models/post_comment.rb
class PostComment  < ApplicationRecord
  belongs_to :user
  belongs_to :post
end
~~~

### 4.PostModelにAssociationを追加する
PostModel が PostCommentModel をたくさん含む事をpost.rbに記載

~~~ruby:app/models/post.rb
class Post < ApplicationRecord
  has_many :post_comments, dependent: :destroy
end
~~~

### 5.UserModelにAssociationを追加する
UserModel が PostCommentModel をたくさん含む事をuser.rbに記載

~~~ruby:app/models/user.rb
class User < ApplicationRecord
  has_many :post_comments, dependent: :destroy  
end
~~~

### 6.Routingを追加する
configフォルダのroutes.rbファイルに追記
~~~ruby:app/models/user.rb
Rails.application.routes.draw do
  resources :posts, only: [:new, :create, :index, :show, :destroy] do
    resources :post_comments, only: [:create, :destroy]   
  end
end
~~~

__Point💡__ 
- `resources~do~end`　[詳しくはこちらを参照](https://railsguides.jp/routing.html)
  - ネストの定義をしている
  - ネストしたURLを作成することで`params[:post_id]`でPostのidが取得できるようになります。
  - resourcesをネストさせると、以下のような操作ができるようになる
  例1) １つの投稿（post）に対して複数のコメント機能(post_comments)を持たせる操作ができるようになる
  例2) １つの投稿（twiit）に対して複数のレビュー機能(いいね/コメント/retwiit)を持たせる操作ができるようになる

### 7.`rails routes`を入力してデータの確認

~~~:Console 
username:~/environment/hoge $ rails routes |grep post_comments
~~~
データを確認して理解を深める 
| HTTP verb | パス | コントローラ#アクション |名前付きルーティングヘルパー|
| :---: | :---: | :---: | :---: |
| POST | /posts/:post_id/post_comments(.:format)| post_comments#create|post_post_comments|
| DELETE | /posts/:post_id/post_comments/:id(.:format) | post_comments#destroy|post_post_comment|

__Point💡__ 
- `|grep post_comments`　(詳しくはこちら)[https://academy.gmocloud.com/know/20210630/12090]
  - `|`(パイプ)は、標準出力された内容を次のコマンドへ橋渡しするために使われるコマンド
  - `grep`は、ファイルから特定の「文字列」が存在するかを調べたいときに利用されるLinuxコマンド


### 8.PostCommentsControllerを作成
~~~:Console　(post_comments_controller作成)
username:~/environment/meshiterro $ rails g controller post_comments
~~~

post_comments_controllerのActionを記載
~~~ruby:app/controllers/post_comments_controller.rb
class PostCommentsController < ApplicationController

  #コメントを作成し、データベースに保存する記述
  def create
    post = Post.find(params[:post_id])
    comment = current_user.post_comments.new(post_params)
    comment.post_id = post.id
    comment.save
    redirect_to post_path(post)
  end

  #
  def destroy
    PostComment.find(params[:id]).destroy
    redirect_to post_path(params[:post_id])
  end

  private

  def post_comment_params
    params.require(:post_comment).permit(:comment)
  end

end
~~~
__Point💡__ 
- `comment = current_user.post_comments.new(post_comment_params)`　
  - `comment = PostComment.new(post_comment_params)`
    `comment.user_id = current_user.id`  の二つを省略したかたち

### 9.post_controllerの編集
コメントを投稿するためのインスタンス変数を定義
~~~ruby:app/controllers/post_controller.rb
class PostController < ApplicationController
:
:
  def show
    :
    :
    @post_comment = PostComment.new
    :
    :
  end
:
:
end
~~~

### 10.app/views/postフォルダのshow.html.erbファイルを編集
favortes_controller.rbを作成
~~~:app/views/posts/show.html.erb
<div>
:
:
    <div>
        <p>コメント件数：<%= @post.post_comments.count %></p>
        <% @post.post_comments.each do |post_comment| %>
            <p><%= image_tag post_comment.user.get_profile_image(100,100) %></p>
            <%= post_comment.user.name %>
            <%= post_comment.created_at.strftime('%Y/%m/%d') %>
            <%= post_comment.comment %>
            <% if post_comment.user == current_user %>
              <%= link_to "削除", post_post_comment_path(post_comment.post, post_comment), method: :delete %>
            <% end %>
        <% end %>
    </div>
    <div>
        <%= form_with model: [@post, @post_comment] do |f| %>
            <%= f.text_area :comment,class: "form-control", placeholder: "コメントをここに" %>
            <%= f.submit "送信する" %>
        <% end %>
    </div>
:
:
<div>
~~~
__Point💡__ 
- `@post.post_comments.count`　
  - `@post` に紐づく `post_comments`のDBの数を数えている
- `post_comment.created_at.strftime('%Y/%m/%d')`　
  - `created_at` は、DBのデータ( __レコード作成時に現在の日付時刻が自動的に設定されるデータ__ )
  - `strftime` とは、日時データを指定したフォーマットで文字列に変換することができるメソッド
- `f.text_area :comment,class: "form-control", placeholder: "コメントをここに"`　
  - `class: "form-control"`とは、 Bootstrapで基本的なformを作る際に必要なクラス
  - [Bootstrapとしての基本形](https://qiita.com/zaburo/items/8983993d173c51cb3827#bootstrap%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E5%9F%BA%E6%9C%AC%E5%BD%A2)


 
### 11.コメント件数の表示を記述
~~~:app/views/posts/index.html.erb
<div>
:
:
    <p><%= link_to "#{post.post_comments.count} コメント", post_path(post.id) %></p>:
:
<div>
~~~
~~~:app/views/users/show.html.erb
<div>
:
:
    <p><%= link_to "#{post.post_comments.count} コメント", post_path(post.id) %></p>:
:
<div>
~~~

## まとめ
コメント機能を作成するには、新たにDB Model Controller の作成をおこない
ModelごとのAssociationをする必要がある！

Formの`text-area`の横幅調整に関してCssに関しては検索で出るがBootStrapを利用した記載が見つからず苦戦💦
Bootstrapで、Formの基本形があったのでclassを追加すると上手くいった(^^♪

見づらいや誤っている記載等あればコメント頂けると助かりますm(__)m
最終的には公式サイトから必要箇所を精査して、理解できるようになりたい！！

## 参考サイト
[Form controls](https://getbootstrap.jp/docs/5.0/forms/form-control/)
[2.7 ネストしたリソース](https://railsguides.jp/routing.html#ネストしたリソース)
[Linuxコマンドで使われるパイプ（|）の使い方を詳しくご紹介！](https://academy.gmocloud.com/know/20210630/12090)
[2.2 スキーマのルール](https://railsguides.jp/active_record_basics.html#%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB) 
[【Rails】 resourcesメソッドを使ってルーティングを定義しよう！](https://pikawaka.com/rails/resources)
[【Rails】 createメソッドの使い方とは？new・saveメソッドとの違い](https://pikawaka.com/rails/create)
[【Rails】 destroyメソッドの使い方とは？](https://pikawaka.com/rails/destroy)
[【Rails】 strftimeの使い方と扱えるクラスについて](https://pikawaka.com/rails/strftime)
[Bootstrap Form おさらい](https://qiita.com/zaburo/items/8983993d173c51cb3827)