book投稿アプリ作成中
はじめに、非同期とは?
非同期リクエストは、ウェブアプリケーションで特定の操作(例: コメントの作成や削除)を行う際に使用される方法です。この方法では、ページの更新や再読み込みをせずに、データの送受信を行うことができます。
前提条件
・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のコメント機能部分を部分テンプレートへ変更する。
form_withへlacal: falseと記述することで、javascript形式になります。
(local: trueだとHTML形式となります。)
、"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 %>
追加した部分テンプレートをshowページに呼び出す。
非同期化にするときはidを指定する。
<div id="comment_area">
<%= render "book_comments/comment", book: @book, book_comment: @book_comment %>
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)%>");
comment_areaの部分は、showページで指定したidです。
コントローラー変更
ユーザーがページを更新せずにデータの送受信を行うため、
ページのリダイレクトは不要なので、redirect_toの部分を削除する。
非同期リクエストでは、JavaScriptやAJAXを使用してデータの送受信が行われます。
Javascriptのファイルで@book と @book_commentを渡しているので、
book_commentsコントローラーでこの値を定義する。(今回は、booksのshowページを参考に)
@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
ひとこと
非同期化中にコントローラーにrenderを追加してしまい、
無限にコメントが作成されてしまいました。
作成されたデータを削除するには、
rails db:migrat:reset
を実行しましょう!
jsファイルに渡す値を間違えないように!
完成イメージ
https://i.gyazo.com/de489f96f9200ea9764eed5fafbb10f4.mp4