コメント機能の実装

内容

  • コメント機能の中身
  • コメント機能の単体テストの内容

バージョン

今回はコメント機能を非同期で実装する流れについて書いていきます。

まずは、ルーティングです。 routes.rb

 resources :posts do
    resources :comments, only: [:create, :destroy]
end

基本的には動画機能に付属させる形で表示しているので、 posts(動画)にネストさせておきます。

次にコントローラーです。

class CommentsController < ApplicationController
  
  def create
    @post = Post.find(params[:post_id])
    @comment = Comment.new(comment_params)
    if @comment.save
      @comments = Comment.where(post_id: @post.id)
      flash.now[:notice] = 'コメントを投稿しました'
    else
      flash.now[:alret] = 'コメントの投稿失敗しました'
    end
  end

  def destroy
    if @comment.destroy
      @comments = Comment.where(post_id: @post)
      flash.now[:notice] = 'コメントを削除しました'
    else
      flash.now[:alret] = 'コメントの削除に失敗しました'
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id, post_id: params[:post_id])
  end
end

今回の場合だとコメント内容(text)とユーザーid, 動画のidが必要になるので、private以下のcomment_paramsに必要なカラムを記入しておきます。

そして今回は非同期の実装を目標にしているため、redirect_toは記述しません。 次にビューです。 今回は動画のページに貼る様にしています。

# 中略
<div class="comments-area">
      <%= render 'comments/comments', commentss: @comments,  remote: true %>
    </div>
    <div class="comment-forms">
      <% if user_signed_in? %>
        <%= form_with model: [@post, @comment], remote: true, method: :post do |f| %>
          <p class="comment-form">コメント投稿画面</p>
          <%= f.text_field :text, class: "comment-form" %>
          <%= f.submit "投稿する", class: "comment-form", id: "comment-botton" %>
        <% end %>
      <% end %>
    </div>
# 中略

今回は動画のページに付属させる様にしています。 次にコメントの中身です。 _comments.html.erb

<% @comments.each  do |comment| %>
  <div class="comments">
    <div class="comment">
        <p class="comment-text"><%= comment.text %></p>
        <p class="comment-name"><%= comment.user.nickname unless comment.user.blank? %></p>
        <% if user_signed_in? && current_user.id == comment.user_id %>
          <%= link_to "削除", post_comment_path(@post.id, comment.id), method: :delete, remote: true, id: "comment-delete" %>
        <% end %>
    </div>
  </div>
<% end %>

本人のみコメントを削除する機能を導入しています。

そして非同期機能を実装するための処理になります。 create.js.erb

$("#comment_text").val("");
$(".flash").html("<%= j(render 'shared/flash') %>");
$(".comments-area").html("<%= j(render 'comments/comments', comments: @comments) %>");
setTimeout("$('.alert').fadeOut('slow')", 2000);

まずは作成の非同期です。 機能の内容としては、送信ボタンが押されたらコメントフォームが空になる様にします。 次にflashメッセージで投稿完了を知らせ、一定時間で消滅します。 そして、コメントが追加されます。

次に削除する場合です。

destroy.js.erb

$(".flash").html("<%= j(render 'shared/flash') %>");
$(".comments-area").html("<%= j(render 'comments/comments', comments: @comments) %>");
setTimeout("$('.alert').fadeOut('slow')", 2000);

コメント下の削除ボタンが押された際に削除を完了を知らせるflashを発生させ、 動画のデータが更新されて、消去されたことがページに反映されます。

追伸

初めて行う機能ではありましたが、いくつか記事を参考にさせていただくことでなんとか終わらせることができました。 今後は非同期で実装する工程が増えてくるかもしれないので、javascript関連の勉強がしなければいけないと感じましたが、必要でなければ、自分からはまだやらなくてもいいという感覚もありました。