【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

コントローラでは、ブックマークの登録、解除の処理を実現し、一覧画面にリダイレクトしていました。

処理の流れ

前回

ブックマークする

  1. ボタンを押してcreateアクション
  2. コントローラーのcreateアクションでブックマークの登録
  3. 一覧画面にリダイレクトして、色付きの⭐️を出してブックマーク状態を表す

ブックマークを解除する

  1. ボタンを押してdestroyアクション
  2. コントローラーのdestroyアクションでブックマークの解除
  3. 一覧画面にリダイレクトして、色なしの⭐️を出してブックマークしていない状態を表す

でした。

今回

ブックマークする

  1. ボタンを押してcreateアクション + ここにremote: trueのオプションを加える。
  2. コントローラーのcreateアクションでブックマークの登録 + jsのファイルにレンダリングされる
  3. jquery(javascript)で、色付き⭐️ボタンのところだけ色なしボタンに切り替える。

ブックマークを解除する

  1. ボタンを押してdestroyアクション + ここにremote: trueのオプションを加える。
  2. コントローラーのdestroyアクションでブックマークの解除 + jsのファイルにレンダリングされる
  3. 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」と同意義のものでした。つまり、これがあることによって、ダブルコーテーションの囲っている部分のずれをなくしているんですね。こういうのをエスケープ処理と言うらしいです。

エスケープ処理の詳細