ブックマークボタンのajax化
ajaxとは
非同期通信と呼ばれる通信方法、通常、クライアントがリクエストを出したらサーバーからのレスポンスが返ってくるまで他の作業をすることができない同期通信と呼ばれる方法が用いられているが、クライアントからサーバーに対して、一部の情報だけを返すようにリクエストを送ることで、それ以外の部分は変わらないので他の作業ができる
ブックマークボタンをクリック時にajax通信を行うには
#_bookmark.html.erb <%= link_to bookmarks_path(board_id: board.id), id: "js-bookmark-button-for-board-#{board.id}", class:"float-right", method: :post do %> <%= icon 'far', 'star' %> <% end %> #_unbookmark.html.erb <%= link_to bookmark_path(current_user.bookmarks.find_by(board_id: board.id)), id: "js-bookmark-button-for-board-#{board.id}", class:"float-right", method: :delete do %> <%= icon 'fas', 'star' %> <% end %>
と現在のブックマークボタンの状態でクリックすると
サーバーログ Processing by BookmarksController#create as HTML
のように通常のブックマーク機能だとHTML形式でリクエストが送信される ここで、ブックマークのリンクヘルパーにremote: trueを指定することでJS形式でリクエストを送信できる
#_bookmark.html.erb <%= link_to bookmarks_path(board_id: board.id), id: "js-bookmark-button-for-board-#{board.id}", class:"float-right", method: :post, remote: true do %> <%= icon 'far', 'star' %> <% end %> #_unbookmark.html.erb <%= link_to bookmark_path(current_user.bookmarks.find_by(board_id: board.id)), id: "js-bookmark-button-for-board-#{board.id}", class:"float-right", method: :delete, remote: true do %> <%= icon 'fas', 'star' %> <% end %>
これによりブックマークボタンをクリックすると
サーバーログ Processing by BookmarksController#create as JS
となり、処理の流れは、bookmarks_controllerのcreate,destroyアクション の通過後はcreate.js.erb,destroy.js.erbファイルに向かうようになる
bookmarks_controller.rbの修正
修正前
#bookmarks_controller.rb class BookmarksController < ApplicationController def create @board = Board.find(params[:board_id]) current_user.bookmark(@board) redirect_back fallback_location: root_path, success: t('.success') end def destroy @board = current_user.bookmarks.find(params[:id]).board current_user.unbookmark(@board) redirect_back fallback_location: root_path, success: t('.success') end end
修正後
#bookmarks_controller.rb class BookmarksController < ApplicationController def create @board = Board.find(params[:board_id]) current_user.bookmark(@board) end def destroy @board = current_user.bookmarks.find(params[:id]).board current_user.unbookmark(@board) end end
とredirect_backの記述を削除
ブックマーク切り替えの処理のJSファイルを作成
HTML形式のリクエストで送信していた時はcreateアクションやdestroyアクションでビューの作成はしていないのでリダイレクト処理でどのページに遷移するか指定していたが、今はremote: trueでJS形式のリクエストで送信しているのでアクション通過後に部分的に更新させるためのJSファイルを作成する
#views/bookmarks/create.js.erb $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/unbookmark', board: @board)) %>"); #views/bookmarks/destroy.js.erb $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/bookmark', board: @board)) %>");
それぞれ、replaceWithでboards/unbookmark、boards/bookmarkをrenderして置き換えているが、javascripthは''や""があるとダメなのでエスケープする必要があるのでj(render~とexcape_javascript(renderのaliasを使っている、replaceWithと似たメソッドとしてhtmlメソッドがあるが、htmlにすると、指定している要素(今回はlink_toで生成されるaタグ)に設定したした値をセットする、今回それぞれ、指定している要素はbookamarkファイルとunbookmarkファイル内に含まれていて、それぞれ設定した値はbookmarkファイルとunbookmarkファイルをセットするので、link_toで生成されたaタグにネストされた形になってしまう。htmlは指定した要素に引数で渡した値をセットするのに、replaceWithは指定した要素に引数で渡した値を置き換えるといった違いがある
参考文献
Rails で JavaScript を使用する - Railsガイド