はじめに
本記事では、コメント機能を非同期通信にした方法を記述しています。
過去に、いいね機能とフォロー機能を非同期通信にしている記事も書いておりますので、
参照ください。
前提
コメント機能は同期通信にはできる状態です。
該当箇所のみの記載です。
コード
コントローラー
food(投稿した食べ物)の詳細画面(show)にてコメントできる仕様です。
show内で完結するので、newメソッドもあります。
createメソッドでもコメントできましたが、
コメントはcommentテーブルに保存するので、newの方が良いと思っています。
省略
def show
@food = Food.find(params[:id])
@like = Like.new
@comment = Comment.new
@comments = @food.comments.order("created_at DESC")
end
省略
ここも特に同期通信と変わりません。
merge(user_id: current_user.id ,food_id: params[:food_id])
ここ忘れないように。
class CommentsController < ApplicationController
def create
@food = Food.find(params[:food_id])
@comment = Comment.create(comment_params)
@comments = @food.comments.order("created_at DESC")
end
private
def comment_params
params.require(:comment).permit(:text).merge(user_id: current_user.id ,food_id: params[:food_id])
end
end
モデル
同期通信と変わりません。
belongs_to
とかhas_many
などですので、省略します。
ビュー
記事を書いててミスを見つけました。
locals
がlacals
になっていました、、、
あっぶね〜😇
・・・
<div class="food-comments-contents-<%= @food.id %>">
クラス名に-<%= @food.id %>
を入れないと何の投稿に対するコメントなのか
わかりませんので、ここが抜けているとリロードしないとコメントが反映されないと思います。
コードが長いので、部分テンプレートにしています。
foods/show.html.erb
省略
<h2 class="show-food-comments-title">Comments !</h2>
<div class="food-comments-contents-<%= @food.id %>">
<%= render partial:"comments/comment", locals: {food: @food} %>
</div>
省略
comments/_comment.html.erb
3行目にremote: true
を入れます。
これにより非同期通信が可能になり、リクエストがjs形式になります。
<div class="comments-comment-contents">
<% if user_signed_in? %>
<%= form_with(model: [@food, @comments],url: food_comments_path(@food,@comment), remote: true) do |f| %>
<%= f.text_area :text, placeholder: "コメントする", rows: "2", class: "food-comment-textbox" %>
<%= f.submit "SEND" ,class: "food-comment-textbox-send" %>
<% end %>
<ul class="show-food-comments">
<% @comments.each do |comment| %>
<li class="show-food-comment">
<div class="comment-food-post-users">
<div>
<%= link_to user_path(comment.user_id) do %>
<% if comment.user.icon.present? %>
<%= image_tag comment.user.icon, class: "icon-img" %>
<% else %>
<i class="fas fa-user-circle"></i>
<% end %>
<% end %>
</div>
<div>
<%= link_to user_path(comment.user_id),class: "comment-food-post-user" do %>
<%= comment.user.nickname %>
<% end %>
<%= comment.text %>
</div>
</div>
</li>
<% end %>
</ul>
<% else %>
<p class="please-login">コメント閲覧・投稿する際は<br/>「新規登録」「ログイン」をお願いします</p>
<% end %>
</div>
comments/create.js.erb
リクエストがjs形式のため、
ファイル名はcreate.js.erb
になります。
先ほどfoods/show.html.erb
にて作った
クラスfood-comments-contents-<%= @food.id %>
が
また部分テンプレートのcomments/comment
に行きます。
これでcreate=コメントした
ということが反映されます。
$(".food-comments-contents-<%= @food.id %>").html("<%= j(render partial: 'comments/comment', locals: {food: @food}) %>")
以上です。
いいねやフォローに比べればまだ簡単なように思えます。
終わりに
私が作成したアプリはコメント機能を非同期化しています。
昨今のアプリでコメント機能が非同期化していないアプリはありませんね。
必ず導入するべきだと思います。
また、いいね機能やフォロー機能を非同期化していれば、
少し考えればコメント機能の非同期化は容易ですので、
いいね機能とフォロー機能の非同期化もマスターしたいところです。
以下参考サイトです。
[Rails]Ajaxを用いて非同期でコメント機能の実装
Railsアプリに非同期通信のコメント機能を実装
明日も頑張ります!!