🪴

Rails 非同期でコメント機能実装

2023/05/08に公開

コメント機能を非同期通信を用いて実装

いいね機能に引き続き、コメント機能を実装!
https://zenn.dev/goldsaya/articles/1e20e5915d15af

実装する機能

  • ビュー
  • コメント一覧を部分テンプレートとすること
  • サーバーからのレスポンスでコメント一覧のテンプレートを返すこと
  • コメントの投稿後、コメントフォームの値に前回の投稿が残らないようにしましょう
  • form_withを使うこと

完成

1. jQueryの記述

Gemfile
gem 'jquery-rails'
bundle install 

2. 非同期したい部分を部分テンプレート化

コメント一覧表示部分

削除ボタンのlink_to部分に、非同期対応にするために
remote:true, data: {"turbolinks" => false}を追記

views/post_comments/_show.html.erb
<div class="d-inline-flex flex-column">
  <% book.post_comments.each do |post_comment| %>
    <div class="d-flex">
    <div class="mb-3">
        <%= image_tag post_comment.user.get_profile_image(50, 50) %><br>
        <%= link_to post_comment.user.name, user_path(post_comment.user) %>
      </div>
      <div class="ml-3">
        <%= post_comment.comment %>
        <% if post_comment.user == current_user %>
        <%= link_to "Destroy" , book_post_comment_path(book, post_comment), class: "btn btn-sm btn-danger" ,method: :delete , remote:true, data: {"turbolinks" => false} %>
      <% end %>
      </div>
    </div>
  <% end %>
</div>

コメント投稿フォーム
form_withにlocal: falseを追記

_form.html.erb
<div class="mt-3">
  <%= form_with model: [ book, post_comment ], local: false do |f| %>
    <%= render 'partial/error_messages', object: f.object %>
    <%= f.text_area :comment, placeholder: "コメントをここに", class: "w-100" %><br>
    <%= f.submit "送信" %>
  <% end %>
</div>

3. idをつける

renderを記述するときidをつける。
コメント件数を表示する部分にもidをつける。

views/books/show.html.erb
<td>コメント件数:<span id="comment_count"><%= @book.post_comments.count %></span></td>

<div id="post-comments">
  <%= render "post_comments/show" , { book: @book , post_comment: @post_comment } %><br>
</div>
<div id="comment-form">
  <%= render "post_comments/form" , { book: @book , post_comment: @post_comment } %>
</div>
books/_index.html.erb
<td>コメント件数:<span id="comment_count"><%= book.post_comments.count %></span></td>

4. コントローラーのredirect先を削除

redirect先を消すことによって、そのアクション名のjsファイルを探しにいくようになる。

controllers/post_comments_controller.rb
class PostCommentsController < ApplicationController
  def create
    @book = Book.find(params[:book_id])
    @user = @book.user
    @post_comment = current_user.post_comments.new(post_comment_params)
    @post_comment.book_id = @book.id
    @post_comment.save
    #redirect_to book_path(@book)
  end


  def destroy
    @post_comment = PostComment.find(params[:id]).destroy
    @post_comment.destroy
    @book = Book.find(params[:book_id])
    #redirect_to request.referer
  end

  private

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

5. js.erb作成

アクション名と一緒のjs.erbを作成

destroy.js.erb
$('#post-comments').html("<%= j(render "post_comments/show", book: @book) %>");
$('#comment_count').html("<%= @book.post_comments.count %>")
create.js.erb
$('#post-comments').html("<%= j(render "post_comments/show", book: @book) %>");
$('#comment_count').html("<%= @book.post_comments.count %>")
$("textarea").val('');

ここではjQueryの記述方法になっている。

jQueryの基本型
$(“セレクタ”).メソッド(“パラメータ[引数]”);

$(“”)の部分にidを入れることでそこの部分を呼び出し、
.html("");の部分で、htmlに対して何をするかを()内に記述してく。
今回はアクション後表示したい部分を記載している。

コメント数のカウント部分に関しては、両方に関することなので両方のファイルに
$('#comment_count').html("<%= @book.book_comments.count %>") で記述。

createの部分は、コメント作成後は削除機能も含めてコメント一覧部分へ表示させたいので、
$('#book-comments').html("<%= j(render "book_comments/commentslist", book: @book) %>");
追加後は、boxをカラにしたいので、$("textarea").val('');としている。


🌱参考にさせていただいた記事

https://zenn.dev/airiswim/articles/2b8a49512614da

https://qiita.com/nakachan1994/items/a7d0957afa9dfd9146ed

復習がてらまた作り直してみました🏋🏻

Discussion