🍎

【Rails】コメント機能実装(非同期通信化)

2023/07/30に公開

はじめに

  • アプリケーション作成済
  • コメント機能(同期)実装済

https://zenn.dev/h_hana/articles/08d1c1deebb19b

1.Gemインストール

Gemfile
gem 'jquery-rails'
ターミナル
$ bundle install

2.部分テンプレートを作成

「コメント一覧」「コメント投稿フォーム」を部分テンプレートにする。

altテキスト

コメントフォーム

app/views/book_comments/_form.html.erb
<%= form_with model: [book, book_comment], local: true do |f| %>
  <%= f.text_area :comment, rows: '5', placeholder: "コメントをここに", class: "w-100" %>
  <%= f.submit "送信する" %>
<% end %>

コメント一覧+削除ボタン

app/views/book_comments/_book_comments.html.erb
<% book.book_comments.each do |book_comment| %>
<tr>
  <td>
    <%= link_to user_path(book_comment.user) do %>
      <%= image_tag book_comment.user.get_profile_image(100, 100) %></br>
      <%= book_comment.user.name %>
    <% end %>
  </td>
  <td><%= book_comment.comment %></td>
  <td>
    <% if book_comment.user == current_user %>
      <%= link_to "削除する", book_book_comment_path(book, book_comment), method: :delete %>
    <% end %>
  </td>
</tr>
<% end %>

3.Ajaxの処理を適用

コメントフォーム

app/views/book_comments/_form.html.erb
<%= form_with model: [book, book_comment], local: false do |f| %> ←「local: false」に変更!
  <%= f.text_area :comment, rows: '5', placeholder: "コメントをここに", class: "w-100" %>
  <%= f.submit "送信する" %>
<% end %>
  • 「local: true」をつけるとhtmlファイルを探す
  • 「local: false」にすることでjsファイルを探す ←今回はこちらで実装!

コメント一覧+削除ボタン

app/views/book_comments/_book_comments.html.erb
<% book.book_comments.each do |book_comment| %>
<tr>
  <td>
    <%= link_to user_path(book_comment.user) do %>
      <%= image_tag book_comment.user.get_profile_image(100, 100) %></br>
      <%= book_comment.user.name %>
    <% end %>
  </td>
  <td><%= book_comment.comment %></td>
  <td>
    <% if book_comment.user == current_user %>
    <!--下記削除するボタンに「remote: true」を追記-->
      <%= link_to "削除する", book_book_comment_path(book, book_comment), method: :delete, remote: true %>
    <% end %>
  </td>
</tr>
<% end %>
  • 削除ボタンを非同期通信化するため、「remote: true」を追記

4.js.erbファイルを作成

3で「local: false」に変更、「remote: true」を追記したことによりJavascriptリクエストが送られるため、JavaScript用のファイルを作成する

  • app/views/book_commentsにファイルを作成
     - comments.js.erb

altテキスト

5.部分テンプレートを読み込む

booksコントローラーのshowページに実装

app/views/books/show.html.erb
 <!--コメント一覧-->
 <div>
   <table>
     <tbody>
       <div id="comments_index"> ←コメント一覧のみ更新するためにidをつける
         <%= render "book_comments/book_comments", book: @books, book_comment: @book_comment %>
       </div>
     </tbody>
   </table>
 </div>
 
 <!--コメントフォーム-->
 <div id="new_comment"> ←コメントフォームのみ更新するためにidをつける
   <%= render "book_comments/form", book: @books, book_comment: @book_comment %>
 </div>

6.js.erbファイルを編集

app/views/book_comments/comments.js.erb
<!--5で指定したid"comments_index"の箇所を、renderで指定した部分テンプレートで更新-->
$("#comments_index").html("<%= j(render 'book_comments/book_comments', book: @book) %>");

<!--フォームを送信したあとにフォームの値を空にする-->
$("textarea").val('');

7.コントローラー編集

book_commentsコントローラーのcreateアクション、destroyアクションを編集する

app/controllers/book_comments_controller.rb
class BookCommentsController < ApplicationController
  def create
    @book = Book.find(params[:book_id])
    comment = BookComment.new(book_comment_params)
    comment.user_id = current_user.id
    comment.book_id = book.id
    comment.save
    redirect_to request.referer  ←この行を削除!
    render :comments     ←この行を追加!
  end
  
  def destroy
    BookComment.find(params[:id]).destroy
    redirect_to request.referer  ←この行を削除!
    render :comments     ←この行を追加!
  end
  
  private
  
  def book_comment_params
    params.require(:book_comment).permit(:comment)
  end
  
end
  • 「redirect_to request.referer」これを削除したことでredirectできなくなり、Javascriptファイルを探しに行くことになる。
  • 「render :comments」を追記したことで、comments.js.erbファイルを探しに行く

以上でコメント機能の非同期通信化が完了となります!!

こちらの記事を参考にさせていただきました🙏

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

Discussion