LoginSignup
23
33

More than 3 years have passed since last update.

【Rails】コメント機能の実装

Posted at

はじめに

ブログっぽいWebサービスにコメント機能を追加してみました。
自分のメモ用、そして同じような機能を実装しようとしている初学者の方の参考になれば幸いです!

前提

Ruby : 2.6.4
Rails : 5.2.3

ユーザー認証にdeviseを使用しています。

Comment Model作成

UserモデルのユーザーがPostモデルに対してコメントをできるようにします。
実装方法としては、フォロー機能のように中間テーブルを用意し、その中間テーブル(Comment Model)のcontentカラムに
実際のコメントを追加します。

$ rails g model comment content:string user:references post:references
$ rails db:migrate
user.rb
  has_many :comments
post.rb
  has_many :comments
comment.rb
class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :post
end

comment.rbについてですが、自分の手動でのミスにより、post_idとの関連付けがうまくいっていない状態で
コメントのテストを行なってしまい、外部キーがnilになってしまいエラーになってしまいました。
この問題の解決は、

comment.rb
class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :post, optional: true
end

このように、optional: true を追記することで(一時的に)解決できます。
ここで、自動テストのありがたみに気づきました(笑)
外部キーのnilを許可するパターンはあまりない気がするので、使うことはそこまでないのかなと思います。

コントローラー作成

comments_controller.rbを作成

$ rails g controller comments
comments_controller.rb
class CommentsController < ApplicationController
  before_action :authenticate_user!

  def create
    post = Post.find(params[:post_id])
    @comment = post.comments.build(comment_params)
    @comment.user_id = current_user.id
    if @comment.save
      flash[:success] = "コメントしました"
      redirect_back(fallback_location: root_path)
    else
      flash[:success] = "コメントできませんでした"
      redirect_back(fallback_location: root_path)
    end
  end

  private

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

createアクションについて。
@comment.user_id = current_user.idを書いている理由として、
上の2行だけではコメントをしたユーザーの関連付けをできないため書いています。

ルーティング

routes.rb
  resources :posts do
    resources :comments, only: [:create]
  end

Views

自分の場合はPostのshow.html.erbにコメント一覧とフォームを追加したかった為ここに追加します。

app/views/posts.show.html.erb
<div class="comment-wrapper border-top mb-10">
  <p class="mt-5">コメント一覧</p>
  <% @comments.each do |c| %>
    <div>
      <% unless c.user.blank? %>
        <a href="<%= user_path(c.user_id) %>"><%= image_tag c.user.image.to_s,
          class:"rounded-circle icon_image mr-3 mb-3"%></a>
        <% end %>
      <%= c.user.username unless c.user.blank? %>
      <br />
      <%= c.content %>
    </div>
    <br />
  <% end %>
  <% if user_signed_in? %>
    <%= form_with(model: [@post, @comment], local: true) do |f| %>
      <%= f.text_area :content, class: "form-control", rows: 5 %>
      <%= button_tag type: "submit", class: "btn btn-success float-right mt-1" do %>
        <i class="far fa-comments"></i> コメントする
      <% end %>
    <% end %>
  <% end %>
</div>

特に難しいことはしていませんが、form_with(model: [@post, @comment], local: true) do |f|は、
commentがpostに紐づいている為配列にします。

posts_controller.rb
  def show
    @post = Post.find(params[:id])
    @comments = @post.comments
    @comment = @post.comments.build
  end

show.html.erb内で使用している@comment@commentsは上記のようになります。

完成

ログインしていない時

スクリーンショット 2019-09-14 23.13.44.png

ログイン時

スクリーンショット 2019-09-14 23.14.02.png

終わりに

コメント削除機能をつけ忘れていたので実装します。
何か間違っている点などありましたらコメントやツイッターでお願いします!

23
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
33