【Rails】簡単なajax処理 (remote true)
はじめに
前回の「【Rails】ブックマーク機能の実装」の発展で、これをajax処理で実現していきます。
ajaxの実装
Railsにおいてajax通信を実装する場合、主に二つの方法があります。
- remote: trueを指定する方法
- JSファイルに任意のタイミングでajax処理を発火させるように記述を施す方法
今回は、より手軽に実装できるremote: trueを使用する方法で実装していきます。
前回まで
_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, remote: true do %> <%= icon 'fas', 'star' %> <% end %>
前回はこちらのコードでbookmarksコントローラのcreateアクションとdestroyアクションを呼び出しました。
bookmarks_controller.rb
class BookmarksController < ApplicationController def create board = Board.find(params[:board_id]) current_user.bookmark(board) redirect_to boards_path, success: t('.success') end def destroy board = current_user.bookmarks.find(params[:id]).board current_user.unbookmark(board) redirect_to boards_path, success: t('.success') end end
コントローラでは、ブックマークの登録、解除の処理を実現し、一覧画面にリダイレクトしていました。
処理の流れ
前回
ブックマークする
- ボタンを押してcreateアクション
- コントローラーのcreateアクションでブックマークの登録
- 一覧画面にリダイレクトして、色付きの⭐️を出してブックマーク状態を表す
ブックマークを解除する
- ボタンを押してdestroyアクション
- コントローラーのdestroyアクションでブックマークの解除
- 一覧画面にリダイレクトして、色なしの⭐️を出してブックマークしていない状態を表す
でした。
今回
ブックマークする
- ボタンを押してcreateアクション + ここにremote: trueのオプションを加える。
- コントローラーのcreateアクションでブックマークの登録 + jsのファイルにレンダリングされる
- jquery(javascript)で、色付き⭐️ボタンのところだけ色なしボタンに切り替える。
ブックマークを解除する
- ボタンを押してdestroyアクション + ここにremote: trueのオプションを加える。
- コントローラーのdestroyアクションでブックマークの解除 + jsのファイルにレンダリングされる
- jquery(javascript)で、色なし⭐️ボタンのところだけ色あり⭐️ボタンに切り替える。
というような流れで処理します。
実装
remote: trueオプション
まず、ボタンにremote: trueのオプションをつけます。
_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 %>
これで、コントローラのレンダリング先がhtmlではなくjsになりました。
コントローラでリダイレクト処理を消す
bookmarks_controller.rb
class BookmarksController < ApplicationController def create @board = Board.find(params[:board_id]) # @boardにしてをつけてインスタンス変数に current_user.bookmark(@board) #@boardに # redirect_to boards_path, success: t('.success') ここだよ end def destroy @board = current_user.bookmarks.find(params[:id]).board # @boardにしてをつけてインスタンス変数に current_user.unbookmark(@board) #@boardに # redirect_to boards_path, success: t('.success') ここだよ end end
これで、リダイレクトされなくなりました。フラッシュメッセージも表示されなくなりました。
createアクションの時は、views/bookmarks/create.js.erb
destroyアクションの時は、views/bookmarks/destroy.js.erbにレンダリングされます。
jsでの処理
create.js.erb
$("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/unbookmark', board: @board)) %>");
この処理は、jqueryで書かれたものです。js-bookmark-button-for-board-<%= @board.id %>はhtmlでのidを指定しています。今回でいうとボタンのところですね。ここを、unbookmarkという部分テンプレートに差し替えてという処理をしています。つまり、ブックマークを解除できる⭐️ボタンに入れ替えてということです。destroy.js.erbではこれの逆をやっています。
destroy.js.erb
$("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/bookmark', board: @board)) %>");
これで、ajax処理化することができました👍
補足
jsでのコードで、j( render(*****) )という部分がありましたよね。「j」ってなんだろうと思って調べてみたら、「escape_javascipt」と同意義のものでした。つまり、これがあることによって、ダブルコーテーションの囲っている部分のずれをなくしているんですね。こういうのをエスケープ処理と言うらしいです。