【Ajax通信】非同期通信でのコメント削除機能

おはようございます。
今日は前回記事を書いたコメント投稿機能に削除機能をAjax通信により実装を行っていきます。
初心者コードで恐縮ですが、簡単にまとめていきたいと思います。

【Ajax通信】非同期でのコメント機能の実装 - さかいの気ままにプログラミング日記

実装までの流れ

① viewに削除ボタンをつくる
② JavaScriptで削除ボタンを押したときコメントidをコントローラーに送信する
③ controllerで受け取ったidのコメントをdestroyする
④ JavaScriptでコメントのHTMLを削除する

① viewに削除ボタンをつくる

まずはビューに削除ボタンを作っていきます。

.comment__box
    .comment__contents
      - @comments.each do |comment|
        .comment__posted{data: {comment_id: "#{comment.id}"}}
          .comment__posted__information
            .comment__user__nickname
              = comment.user.nickname
            .comment__post__time
              = comment.created_at.strftime("%Y年%m月%d日 %H:%M")
          .comment__posted__box
            .comment__posted__content
              = comment.content
            - if current_user.id == comment.user_id 
              %button.comment__delete__button
                %i.far.fa-trash-alt



.comment__posted{data: {comment_id: "#{comment.id}"}}

投稿されたコメントの識別をするためにカスタムデータ特性を追加しています。hamlの記法では文字列の中に#{}で囲うことで変数を使用することができます。


- if current_user.id == comment.user_id

コメント削除はログイン中のユーザーとコメントしたユーザーが一致したときのみ行えるようにします。


JavaScriptで削除ボタンを押したときコメントidをコントローラーに送信する

$(document).on('click', '.comment__delete__button', function(){
    var comment_data_id = $(this).parent().parent().data("comment-id")
    var url = "/events/" + gon.event.id + "/set_lists/" + gon.set_list.id + "/comments/" + comment_data_id
    $.ajax({
      url: url,
      type: "DELETE",
      data: comment_data_id,
      datatype: "json"
    })


$(document).on('click', '.comment__delete__button', function(){

ユーザーがコメントを送信した直後でも削除ができるように(コメント投稿後にページ遷移することなく削除ボタンを押した場合)、セレクタの取得は$(document).on(~~ で記載するようにしています。


var comment_data_id = $(this).parent().parent().data("comment-id")

削除するコメントidを取得しています。.data("comment-id")では①で追加したカスタムデータ属性を取得しています。このカスタムデータ特性はコメントidと紐付いているので、削除ボタンを押したコメントを削除することができるというロジックになります。


var url = "/events/" + gon.event.id + "/set_lists/" + gon.set_list.id + "/comments/" + comment_data_id

遷移させるurlを指定しています。今回はルーティングをネストさせているので複雑ですが、gonのGemを使いながら記載しています。gonはコントローラーで定義したインスタンス変数をJavaScriptで使えるようにしてくれるGemですごく便利で簡単に実装できるのでよく使っています。gonの導入の仕方は下記事に乗せておきます。

【gem gon】Railsで定義した変数をさくっとJavascriptで使う - Qiita


$.ajax({ ~~

Ajax通信するための記載をしています。
url : 上で定義した遷移先のurlを指定します。
type : 今回はHTTPメソッドはDELETEを使用するので、DELETEを指定します。
data : DELETEメソッドを行う場合は、コントローラーに送るデータは削除するレコードのidです。なので、上で定義した削除するcomment_idを指定します。
datatype : もちろんjsonです。

③ controllerで受け取ったidのコメントをdestroyする

次にコントローラーに処理を書いていきます。

def destroy
    @comment = Comment.find(params[:id])
    @comment.destroy
    respond_to do |format|
      format.json { render json: @comment.id }
    end
  end


respond_to do |format| ~~ end

リクエストのフォーマット毎の処理をするために記載しています。これを記載しないとサーバーエラーになります。


format.json { render json: @comment.id }

次にJavaScript側でコメントを削除しないといけないので、返すデータは削除したコメントのidを書いています。
ここで、format.html { redirect_to ~~ } としてもなぜか走ってしまいます。format.json ~~ の後ろに書くとformat.jsonが走り、前に書くとformat.htmlが走るのが確認できました。コントローラーに値がjson形式で送られてきたらformat.jsonが走るものだと思っていたのですが、ここがいまだに謎です。。
また、分かれば記事書くかもです。

④ JavaScriptでコメントのHTMLを削除する

Ajax通信が成功したときの処理を書いて終了です。

.done(function(comment_id){
      $('[data-comment-id = '+ comment_id + ']').remove();
    })


$('[data-comment-id = '+ comment_id + ']').remove()

カスタムデータ特性から削除するコメントのセレクタを取ってきてremove()します。カスタムデータ属性からセレクタを取ってくるには[ ]を使います。

終わり!!



ここまで読んでくださり、ありがとうございました。
次はいいね機能の実装について書いていきたいと思います
分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!