railsでの非同期通信の実装方法
railsでの非同期通信の実装方法
railsでの非同期通信の実装手順は、[remote: true]オプションを付与する方法とJSファイルに任意のタイミングでAjax処理を発火させるように記述する方法がある。
今回は、簡単な[remote: true]オプションを付与する方法を説明します。
①クライアント側で動作することでサーバーにリクエストを送る部分(link_toやform_withなど)にremote: trueと記載することで、railsの通信は非同期通信になる。
↓
②サーバー側では、remote: trueのオプション付きでリクエストが送られてきて、いつも通り(ルーティング→コントローラーの対応しているアクション→DBへのアクセスが必要な処理の場合は、モデルに側でクエリを発行してDBへアクセス)の処理がされ、remote: trueがある事により、レスポンスのファイルは、htmlファイルではなく対応しているjsファイルがクライアントにレスポンスされる。
※非同期通信にする際は、リダイレクトやレンダーを指定しない。
リダイレクトやレンダーを指定しなければ、[app/views/コントローラ名/アクション名.js.erb]ファイルがクライアントにレスポンスされる。(js.erbファイルは、jsファイルでRuby記述も入れられるファイル。)
↓
レスポンスとして[js.erb]ファイルを受け取った、クライアントはブラウザ上で受け取ったファイルを元にJavaScriptを実行する。
実際の具体例を以下に記述します。
[app/views ファイル] <%= link_to bookmark_path(board.bookmarks.find_by(user_id: current_user.id)), id: "js-bookmark-button-for-board-#{board.id}", method: :delete, remote: true do %> <i class="fas fa-star"></i> <% end %>
上記の記述で[link_to]に[remote: true]オプションを付与しているので、クライアント側が上記のアイコンをクリックしたら、サーバー側に非同期通信でのリクエストを送る。
↓
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
送られてきたリクエストは、ルーティングを元に対応しているコントローラーのアクション側で処理される。
上記のようにそれぞれのアクションにリダイレクトやレンダーを記述していないので、[app/views/コントローラー名/create.js.erb]や[app/views/コントローラー名/destroy.js.erb]ファイルがクライアント側にレスポンスされる。
↓
[app/views/bookmarks/create.js.erb] $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/bookmark', board: @board)) %>");
上記のような場合は、まずサーバー側でrender処理をしてから、上記ファイルをクライアント側にレスポンスする。
イメージは、以下のようなものをレスポンスする感じになる。
$("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("[app/views/boards/_bookmark.html.erb]ファイルの内容");
※ポイント
jQueryの[replaceWith]と[html]の違い
以下のようなコードがあった場合の例を示します。
[ブラウザ上でのHTML] <div id="greeting">Hello</div>
[app/views/js.erb ファイル] $("#greeting").replaceWith("こんにちは");
上記のような場合は、ブラウザ側で実行され以下のような結果になる。
[ブラウザ上でのHTML]
こんにちは
[app/views/js.erb ファイル] $("#greeting").html("こんにちは");
上記のような場合は、ブラウザ側で実行され以下のような結果になる。
[ブラウザ上でのHTML] <div id="greeting">こんにちは</div>
[replaceWith]は、対応している実際の要素($("")の部分)を全部replaceWithの引数に置き換える。
[html]は、対応している部分の要素($("")の部分)の内容を置き換える。
j(render)とは
escape_javasciptの事で、JavaScriptは[""]や['']があるとダメなので、エスケープする必要がある。
同期通信と非同期通信
・同期通信は、ブラウザとサーバーがやり取りする。
・非同期通信は、ブラウザに入っているJavaScriptがブラウザの代わりにサーバーとやり取りする。
jQueryとは
・JavaScriptで出来ることを簡単に記述できるようにしたJavaScriptのライブラリ。
・JavaScriptは、各ブラウザに搭載されたエンジンにより実行されるが、jQueryはブラウザ毎の記述の違いを吸収してくれる。
・jQueryは、基本的にHTMLのDOM操作やAjax処理を簡単に記述する為のものなので、それ以外の処理(数値の足し算や配列データの操作)は、JavaScriptコードで記述する必要がある。
jQueryの使い方は、以下のようになる。
[app/views/js.erb ファイル] $("#aaa"); # HTMLからidが[aaa]のDOMを取得する。 $(".aaa"); #HTMLからclassが[aaa]のDOMを取得する。 $("#aaa").html("こんにちは"); #先のように取得したDOMに対してメソッドを使う。
以下のように[app/views/js.erb]ファイルに$(function() {}を記載しない説明は、以下のようになる。
[app/views/bookmarks/create.js.erb] $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/bookmark', board: @board)) %>");
htmlファイル内に直接jQueryを埋め込んで利用する場合は、scriptタグで囲って$(function() {}を記述しなければ、基本的に動かないが、
今回のようにjs.erbファイルにjQueryを記載する際は、functionを記載しなくても動くが、functionを記載した方が分かりやすくなり、意味不明なエラーなども回避できるので、js.erbファイルにもfunctionを記載した方が良い。($(function() {}によって、HTMLが読み込まれるのを待ってからjQueryが実行される。)
参考記事:
「Ruby on Railsで簡単で素早くWebアプリを開発する」 最終回 Rails + jQuery でAjaxを使ってみよう
ブックマークボタンのajax化 - olive_miuのブログ
【Rails】簡単なajax処理 (remote true) - bokuの学習記録
escape_javascriptメソッドって何ぞや。 - Qiita
今さら聞けない!jQueryとは【初心者向け】 | TechAcademyマガジン
JS形式のレスポンスと remote: true を使う - Qiita
jQuery 要素を置き換える(replaceWith/replaceAll) | ITSakura
railsで普通のリンクをajax通信に変更するテンプレートセット - Qiita
Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう!(いいね機能のデモ付) - Qiita
Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう!(いいね機能のデモ付) - Qiita
jquery — jQuery replaceWith()とhtml()の違いは何ですか?
【IT用語】 Ajaxとは?初心者向けに豊富な画像で仕組みを解説 | Pikawaka
【Rails】 remote: trueでフォーム送信をAjax実装する方法とは? | Pikawaka
Ajax(非同期通信)についてわかりやすさ重視でまとめてみた(Rails使用のデモ付) - Qiita
【Rails入門】ajaxの使い方まとめ | 侍エンジニアブログ
【Rails】 respond_toメソッドの使い方まとめ | Pikawaka
$(function(){})ってどういう意味?jQueryのおまじないをわかりやすく解説します – More Web
Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう!(いいね機能のデモ付) - Qiita