LoginSignup
0
0

More than 1 year has passed since last update.

オリジナルアプリのコメント機能を非同期で投稿出来るように変更した時の備忘録

Last updated at Posted at 2022-09-10

オリジナルの写真と投稿アプリを作成した時にコメント機能に後からAjaxで実装してみようと思ったらかなり手こずったので忘れない為に備忘録を残します。
投稿した写真にログインしたユーザーがコメント出来る機能になってます。

コントローラーの編集

投稿した写真の詳細ページにコメントしたいのでアクションはcreateとdestroyの二つ
画面遷移はしたくないのでrenderやredirectの記述はしない
@comment = Comment.find(params[:id])をdestriyメソッドの下に書くと意味がないので一番上に記述する

comments_controller.rb
 def create
    @post = Post.find(params[:post_id])
    @comment = Comment.new(comment_params)
    @comment.save
  end

  def destroy
    @comment = Comment.find(params[:id])
    @post = Post.find(params[:post_id])
    @post_comments = @post.comments
    Comment.find_by(id: params[:id], post_id: params[:post_id]).destroy
  end

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

フォームの編集と部分テンプレートの追記

form_withのlocalオプションをfalseにする
投稿したコメントを表示するための部分テンプレートを挿入

show.html.erb
 <%= form_with model: [@post, @comment], local: false do |f|%>
      <div class="post-field">
         <%= f.label :text, "コメント" %>
         <%= f.text_area :text, class: :post_text_field %>
      </div>
     <div class="show__comment__actions">
       <%= f.submit "コメントを投稿する", class: :comment_form__btn  %>
    </div>
 <% end %>

<ul class="show_comments_lists">
    <%= render "comments/comments", post: @post, comments: @comments %>
</ul>

投稿したコメントを表示するための部分テンプレートを作成

link_toにはremote: trueを追記する

_comments.html.erb
<% post.comments.each do |comment| %>
  <li id="comment_<% @comment.id %>" class="show_comments_list">
     <%= comment.text %><br>
     by@<%=  comment.user.name %>
      <% if user_signed_in? && current_user.id == comment.user_id  %>
       <%= link_to "コメントを削除する", post_comment_path(comment.post, comment),  method: :delete, remote: true, class: :post_delete_btn %>
       <% end %>   
  </li>
<% end %>

*ここで注意なのがidの指定に<% @comment.id %>を記述すること。削除機能を実装する際に重要になる。

下準備が終了したのでAjaxでの投稿機能と削除機能を書いていく

コメントを投稿するためのJavaScriptファイルを作成

create.js.erb
$("textarea").val('');
$('.show_comments_lists').html("<%= j(render 'comments/comments', post: @post, comment: @comment) %>");

*コメントが投稿された後にフォームを空にしたいのでtextareaのvalue属性をval('');と記述
コメントを表示するためにhtml()を記述してrenderで指定した部分テンプレートに更新させる。(jはescape_javascriptの略)

コメントを削除するためのJavaScriptファイルを作成

$('#comment_<%= @comment.id %>').remove();
$('.show_comments_lists').html("<%= j(render 'comments/comments', post: @post, comment: @comment) %>");

ここが一番手間取った…
remove()にshow_comments_listsを指定するとコメントが全て削除されるのでcomment_<%= @comment.id %>を指定。
@comment.idはコントローラーにdestroyアクションに@comment = Comment.find(params[:id])を記述しているから使える(まずこれを書いていなかったのでエラーが発生しまくった)

あと勘違いしていたのがremove()。てっきり削除した上で画面の表示を変えてくれるのかと思ってたら削除しかしないメソッドだった。
なのでcreate.js.erbと同様にrenderで指定した部分テンプレートに更新させるための記述を追記 。

以上でAjax化終了
参考になる記事があった上で実装にかなり手間取ったのでコントローラーでの変数の指定する際の意味やメソッドの特性をもっと知るべきだなと感じました。

参考にさせて頂いた記事はこちらです。
https://qiita.com/coneco12_/items/61174a80a611b7e0049e

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0