🍎
【Rails】コメント機能実装(非同期通信化)
はじめに
- アプリケーション作成済
- コメント機能(同期)実装済
1.Gemインストール
Gemfile
gem 'jquery-rails'
ターミナル
$ bundle install
2.部分テンプレートを作成
「コメント一覧」「コメント投稿フォーム」を部分テンプレートにする。
コメントフォーム
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
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ファイルを探しに行く
以上でコメント機能の非同期通信化が完了となります!!
こちらの記事を参考にさせていただきました🙏
Discussion