[Rails] コメント機能の実装

結構個人的には苦労したため備忘録です。

利用環境
・ruby 2.7.3
・Rails 6.1.4

## 実装内容
ユーザの投稿(post)に対してコメント機能(comment)の実装
CommentテーブルはPostとUserの中間テーブルとします。
PostとUserはすでに作成済み前提で記載します。
コメント機能と関係のないコードは省略しております。

## モデル作成
Commentモデルの作成

```terminal:ターミナル
$ rails g model Comment content:text user_id:integer post_id:integer
$ rails db:migrate
```

## アソシエーション（関連付け）
それぞれのモデルに下記を追記する。
`dependent: :destroy` は `user` が削除された際に `post` と `comment` も同時に削除させるため

```ruby:app/models/user.rb
class User < ApplicationRecord

 has_many :posts, dependent: :destroy
 has_many :comments, dependent: :destroy

end
```

```ruby:app/models/post.rb
class Post < ApplicationRecord

  belongs_to :user
  has_many :comments, dependent: :destroy

end
```

```ruby:app/models/comment.rb
class Comment < ApplicationRecord

  belongs_to :user
  belongs_to :post
  validates :content, presence: true

end
```

## コントローラーの作成と編集

`comments` コントローラーを作成

```terminal:ターミナル
$ rails g controller comments
```

`posts` と `comments` コントローラーの編集

```ruby:app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments.order(created_at: :desc)
  end

end
```

```ruby:app/controllers/comments_controller.rb
class CommentsController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    # 投稿に紐づいたコメントを作成
    @comment = @post.comments.build(comment_params)
    @comment.user_id = current_user.id
    @comment.save
    redirect_to @post
  end

  def destroy
    @comment = Comment.find(params[:id])
    @comment.destroy
    redirect_to @post
  end

  private

  def comment_params
    params.require(:comment).permit(:content, :post_id, :user_id)
  end

end
```

## ルートの設定

```ruby:config/routes.rb
Rails.application.routes.draw do

  resources :users
  resources :posts, only: [:index, :show, :new, :create] do
    resources :comments, only: [:create, :destroy]
  end

end
```

## Viewファイル

```erb:app/views/posts/show.html
<div class="row">
  <% if user_signed_in? %>
    <div class="comment-create">
      <h3 class="text-left">コメントを投稿する</h3>
      <%= render partial: 'comments/form', locals: { comment: @comment, post: @post } %>
    </div>
  <% end %>
  <hr>
  <h2 class="text-comments">コメント一覧</h2>
  <div class="comments_area">
    <%= render partial: 'comments/index', locals: { comments: @comments } %>
  </div>
</div>
```

```erb:app/views/comments/_index.html
<!---- コメント内容 ----->
<a class="comment-count">コメント数<%= comments.count %>件</a>
<% comments.each do |comment| %>
  <% unless comment.id.nil? %>
    <div class="comment-box">           
      <p> <%= comment.user.username %> <%= comment.created_at.strftime('%Y/%m/%d %H:%M:%S') %></p>
      <%= simple_format(h comment.content) %>
      <% if comment.user == current_user %>
        <%= link_to post_comment_path(comment.post_id, comment.id), method: :delete, remote: true, class: "comment_destroy" do %>
          <i class="fas fa-trash" style="color: black;"></i>
        <% end %>
      <% end %>
    </div>
  <% end %>
<% end %>
```

```erb:app/views/comments/_form.html
<!---- コメント入力フォーム ----->
<%= form_with(model: [post, comment], url: post_comments_path(@post) ) do |f| %>
    <%= f.text_area :content, size: "10x5", class:"area-field" %>
    <%= f.submit "書き込む", class:"submit-btn" %>
<% end %>
```

こんな感じでコメント機能は終わりです。