0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

コメント機能の非同期化

Last updated at Posted at 2023-07-04

book投稿アプリ作成中
:hatching_chick:はじめに、非同期とは?
非同期リクエストは、ウェブアプリケーションで特定の操作(例: コメントの作成や削除)を行う際に使用される方法です。この方法では、ページの更新や再読み込みをせずに、データの送受信を行うことができます。

:point_up:前提条件
・device導入 ・Bootstrap導入
・ユーザー機能実装済(Userモデル)
・投稿機能実装済(Bookモデル)
・コメント機能実装済(Book_Commentモデル)


jQueryインストール
Gemfileに以下を追加

gem "jquery-rails"

javascript/packs/application.jsに以下を追加

import "jquery";

インストール

$ bundle install

今回、部分プレートにする元のshowページです。

 <!--コメント機能-->
        <div>
          <table>
         <% @book.book_comments.each do |book_comment| %>
          <tr>_
            <td>
             <%= link_to user_path(@book.user.id) do %>
             <%= image_tag book_comment.user.get_profile_image(50,50) %><br>
             <%= @book.user.name %>
             <% end %>
             </td> 
             <td><%= book_comment.comment %></td> 
             <td>
              <% if book_comment.user == current_user %>
              <%= link_to "Destroy", book_book_comment_path(book_comment.book,book_comment), method: :delete, class: "btn btn-sm btn-danger"%>
              <% end %>
             </td>
           </tr>
         <% end %>
         </table>
        </div>
          
          <div>
             <%= form_with model: [@book, @book_comment] do |f| %>
             <%= f.text_area :comment, rows: '5',placeholder: "コメントをここに", class: "form-control comment" %>
             <%= f.submit "送信", class: "btn btn-lg btn-base-1 mt-20 pull-right" %>
            <% end %>
          </div>

コメント機能用の部分テンプレートを作成
今回は、book_commentsディレクトリ内に
_comment.html.erbを作成しました。

books/show.html.erbのコメント機能部分を部分テンプレートへ変更する。

:star:form_withへlacal: falseと記述することで、javascript形式になります。
local: trueだとHTML形式となります。)

:star:、"Destroy"の<%= link_to のところに、remote: trueを追記すること

javascript形式でリクエストを送ることでページをリロードせずに一部のみ変更が可能です。

_comment.html.erb

<!--コメントリスト部分プレート-->
  <table>
    <% book.book_comments.each do |book_comment| %>
      <tr>
        <td>
          <%= link_to user_path(book.user.id) do %>
            <%= image_tag book_comment.user.get_profile_image(50,50) %><br>
            <%= book.user.name %>
          <% end %>
        </td> 
        <td><%= book_comment.comment %></td> 
        <td>
          <% if book_comment.user == current_user %>
          <!--remote: trueを追加-->
+           <%= link_to "Destroy", book_book_comment_path(book_comment.book,book_comment), method: :delete,remote: true, class: "btn btn-sm btn-danger"%>
          <% end %>
        </td>
      </tr>
    <% end %>
  </table>

   <!--コメントフォーム部分プレート-->
   <!--local: falseを追加-->
+  <%= form_with(model: [book, book_comment], local: false, class: "comment-form") do |f| %>
    <%= f.text_area :comment, rows: '5', class: "form-control comment" %>
    <div>
      <%= f.submit "送信" %>
    </div> 
  <% end %>

:shamrock:追加した部分テンプレートをshowページに呼び出す。
非同期化にするときはidを指定する。

 <div id="comment_area">
         <%= render "book_comments/comment", book: @book, book_comment: @book_comment %>

:shamrock:javascriptのファイル作成

book.commentディレクトリ内に作成(コントローラーのアクション名で作成する。)
create.js.erb&destroy.js.erbを作成

create.js.erb

$("#comment_area").html("<%=j(render 'book_comments/comment', book: @book, book_comment: @book_comment)%>");

destroy.js.erb

$("#comment_area").html("<%=j(render 'book_comments/comment', book: @book, book_comment: @book_comment)%>");

:point_up:comment_areaの部分は、showページで指定したidです。


:shamrock:コントローラー変更

:star:ユーザーがページを更新せずにデータの送受信を行うため、
ページのリダイレクトは不要なので、redirect_toの部分を削除する。
:star:非同期リクエストでは、JavaScriptやAJAXを使用してデータの送受信が行われます。

:star:Javascriptのファイルで@book@book_commentを渡しているので、
book_commentsコントローラーでこの値を定義する。(今回は、booksのshowページを参考に)

:star: @book_comment = BookComment.newを指定することで投稿、削除後に投稿内容が残らないようにしています。

book_comments_controller.rb

class BookCommentsController < ApplicationController
  def create
    book = Book.find(params[:book_id])
    comment = current_user.book_comments.new(book_comment_params)
    comment.book_id = book.id
    comment.save 
+   @book = Book.find(params[:book_id])
+   @book_comment = BookComment.new
-   redirect_to book_path(book)
  end
  
  def destroy
    BookComment.find(params[:id]).destroy
+    @book = Book.find(params[:book_id])
+   @book_comment = BookComment.find_by(id: params[:id], book_id: params[:book_id])
+   @book_comment = BookComment.new
-   redirect_to book_path(params[:book_id])
  end
  
  private
  def book_comment_params
    params.require(:book_comment).permit(:comment)
  end
end

books/showアクション

def show
    @book = Book.find(params[:id])
    @user = @book.user
    @book_new = Book.new
    @book_comment = BookComment.new 
  end

:hamster:ひとこと
非同期化中にコントローラーにrenderを追加してしまい、
無限にコメントが作成されてしまいました。:sweat_smile:
作成されたデータを削除するには、
rails db:migrat:resetを実行しましょう!

jsファイルに渡す値を間違えないように!

:star2:完成イメージ
https://i.gyazo.com/de489f96f9200ea9764eed5fafbb10f4.mp4

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?