#Bootstrap使用
非同期化とは?
・送信者のデータ送信タイミングと受信者のデータ受信タイミングを合わせずに通信を行う通信方式を指します。
・画面全体を更新せずに、一部だけ更新すること
jQueryインストール
Gemfile
gem "jquery-rails"
インストール行う
$ bundle install
部分テンプレートを作成
どこに作成してもいいのですが、今回は、favoriteディレクトリに作成
favorite/_favorite-btn.html.erb
部分テンプレート_favorite-btn.html.erb
<% if book.favorited_by?(current_user) %>
<%= form_with(url: book_favorites_path(book), method: :delete, remote: true, class: "unlike-form", local: true) do |f| %>
<%= f.button type: :submit, class: "unlike-btn" do %>
<i class="fas fa-heart" style="color: red;"></i>
<%= book.favorites.count %>
<% end %>
<% end %>
<% else %>
<%= form_with(url: book_favorites_path(book), method: :post, remote: true, class: "like-form", local: true) do |f| %>
<%= f.button type: :submit, class: "like-btn" do %>
<i class="far fa-heart"></i>
<%= book.favorites.count %>
<% end %>
<% end %>
<% end %>
favorites_controller
redirect_to request.refererを消す。
createアクション
対応するBookオブジェクトをデータベースから検索します。その後、ログインしているユーザーに関連付けられたFavoriteオブジェクトを作成し、そのお気に入りを保存します。
destroyアクション
対応するBookオブジェクトをデータベースから検索します。その後、ログインしているユーザーに関連付けられたお気に入りを検索し、該当するお気に入りを削除します。
class FavoritesController < ApplicationController
def create
@book = Book.find(params[:book_id])
book = Book.find(params[:book_id])
favorite = current_user.favorites.new(book_id: book.id)
favorite.save
-redirect_to request.referer
end
def destroy
@book = Book.find(params[:book_id])
book = Book.find(params[:book_id])
favorite = current_user.favorites.find_by(book_id: book.id)
favorite.destroy
-redirect_to request.referer
end
end
各link_toにremote: trueを付け加えて非同期化する場合
_favorite-btn.html.erb
<% if book.favorited_by?(current_user) %>
<%= link_to book_favorites_path(book), method: :delete, remote: true do %>
<i class="fas fa-heart" aria-hidden="true" style="color: red;"></i>
<%= book.favorites.count %> いいね
<% end %>
<% else %>
<%= link_to book_favorites_path(book), method: :post, remote: true do %>
<i class="fas fa-heart" aria-hidden="true"></i>
<%= book.favorites.count %> いいね
<% end %>
<% end %>
form_withとlocal:falseで非同期化する場合
____________________
if文を使用して、bookが現在のユーザーによっていいねされているかどうかをチェックしています。
book.favorited_by?(current_user)は、bookが現在のユーザーによっていいねされているかどうかを確認するメソッドです。
いいねされている場合は、form_withを使用して削除のリクエストを送信するフォームを作成します。
フォームのurl属性にはbook_favorites_path(book)が設定され、method属性には:deleteが指定されます。また、local:falseを使用して非同期通信を有効にします。
f.buttonメソッドを使用してボタンを作成し、いいねの数を表示します。
いいねされていない場合は、同様にform_withを使用して作成のリクエストを送信するフォームを作成します。
フォームのurl属性にはbook_favorites_path(book)が設定され、method属性には:postが指定されます。
また、CSSクラスを使用してボタンのスタイリングを行っています。
これにより、いいねボタンが表示され、非同期通信を使用していいねの追加や削除が行われるようになります。
<% if book.favorited_by?(current_user) %>
<%= form_with(url: book_favorites_path(book), method: :delete, local:false, class: "unlike-form") do |f| %>
<%= f.button type: :submit, class: "unlike-btn" do %>
<i class="fas fa-heart" style="color: red;"></i>
<%= book.favorites.count %>
<% end %>
<% end %>
<% else %>
<%= form_with(url: book_favorites_path(book), method: :post, local:false, class: "like-form") do |f| %>
<%= f.button type: :submit, class: "like-btn" do %>
<i class="far fa-heart"></i>
<%= book.favorites.count %>
<% end %>
<% end %>
<% end %>
favorites
のディレクトリ内に
create.js.erb
と destroy.js.erb
を作成
(ファイル名はアクション名と同じものにします。)
create.js.erb
&destroy.js.erb
に以下を追加
$("#favorite_buttons_<%= @book.id %>").html("<%= j(render 'favorites/favorite-btn', book: @book) %>")
$("#favorite_buttons_<%= @book.id %>")
は、お気に入りボタンを表示するためのコンテナです。
.html("<%= j(render 'favorites/favorite-btn', book: @book) %>")
は、選択したHTML要素の中身を指定のコンテンツで置き換える操作を行います。具体的には、'favorites/favorite-btn'という部分テンプレートをレンダリングし、その結果をHTMLコンテンツとして設定します。この部分テンプレートは、いいねボタンを表示するためのHTMLを含んでいます。
したがって、この行のコードは、特定のHTML要素の中身をお気に入りボタンのHTMLに置き換えるという意味を持ちます。これにより、非同期通信の結果を反映して、お気に入りボタンが更新されます。
_index.html.erb
・いいねボタンを追加する。
id="favorite_buttons<%= book.id %>">
は、特定の本のお気に入りボタンとお気に入り数を表示するHTMLテーブルセルです。
<%= render "favorites/favorite-btn", book: book %>
は、favorites/favorite-btnという部分テンプレートをレンダリングして表示します。部分テンプレート内で、本のお気に入りボタンとお気に入り数が表示されます
<td id="favorite_buttons_<%= book.id %>">
<%= render "favorites/favorite-btn",book:book %> </td>
最後にbooks/index.html.erbにいいねボタンを追加するため_index.html.erbを呼び出す
(インスタンス変数@booksを定義)
books/index.html.erb
<%= render 'index', books: @books %>