本記事ではRailsでのAjaxリクエストについての解説を行います。
RailsでのAjaxの実装
ビュー側
link_toメソッドのオプションに下記の記述を追加します。
1 |
remote: true |
これだけでリンクをクリックしただけでAjaxリクエストをサーバに送信できます。
コントローラ側
下記の記述をします。
1 |
head :no_content |
レスポンスボディなしでHTTPステータスコードを204で返すという記述になります。(別に記述はぶっちゃけなくても動きますが明示的に書いています。)
JavaScript
JavaScript側でサーバ側のAjaxリクエストで依頼した処理結果を画面に反映させる必要があります。下記はturbolinksを利用している場合の記述ですが利用していない場合はwindows.onloadに書き換えて下さい。
1 2 3 4 5 6 7 |
document.addEventListener('turbolinks:load', function() { document.querySelectorAll('削除ボタンのクラス').forEach(function(HTML要素名) { HTML要素名.addEventListener('ajax:success', function() { 行いたい処理内容 }); }); }); |
Ajax通信が成功した際はRailsがajax:successというイベントを発行してくれるのでこれに対応するイベントリスナーになります。Ajax通信が成功したらこのイベントリスナーがキャッチしてくれるので非同期に行いたい処理を記述しましょう。
RailsでAjax通信を実現している仕組み(rails-ujs)
link_toに「remote: true」というオプションを加えるとAjaxでリクエストを送信する仕組みは「rails-ujs」というActionViewのJavaScriptライブラリによって処理されています。またAjax通信が成功した場合(ステータスコードが2XXの場合)は「ajax:success」イベントを発行してくれるので画面側では任意のタイミングで画面更新等の処理を行うことが可能です。
なお、rails-ujsはRails5.1からでそれまではjquery-railsというJavaScriptライブラリが使われていたようです。
失敗した場合は
「ajax:error」イベントが処理されます。
その他のrails-ujsの機能(Ajax以外にも様々な画面機能がある。)
data-confirm
確認ダイアログを表示してくれます。
data-disabled-with
submitボタンの属性の一つでフォームの二重クリックを防止してくれます。
RailsのAjaxリクエストのセキュリティ対策
RailsではAjaxリクエスト内にもセキュリティトークンの埋め込みをしています。
トークンを埋め込む仕組み
Ajaxが動く画面内にあらかじめRailsがセキュリティトークンを出力しておき、そのトークン情報をAjaxのX-CSRF-TokenというHTTPヘッダで送る形になります。
トークンの出力
csrf_meta_tagsヘルパーにて行います。共通レイアウトのapplication.html.erbでもこのヘルパーでヘッダ内に出力しています。
トークンの送信
Railsが自動的に行うAjaxリクエストは自動でサポートしますし、自分でAjaxリクエストを行う場合は下記のメソッドを使います。
1 |
Rails.ajax() |
ただ、上記メソッドはContent-Typeを「application/x-www-form-urlencoded 」で送信することになるのでJSONでデータを送信したい場合は不便です。
また、jQueryのAjaxリクエストを使う場合はデフォルトでRailsのトークン埋め込みを行ってくれますが、rails-ujsよりも前にjQueryライブラリファイルが読み込まれている必要があるので注意しましょう。
SJR
Ajax通信をした後にその結果をブラウザ側で処理する方法としてはAjaxのリクエストボディにJavaScriptコードを返却してそれをブラウザ側で実行するという方法があります。(他にはクライアント側でイベントリスナーを作ってAjaxのリクエスト結果を処理する方法もありましたが。)これをServer-generated JavaScript Responses(SJR)といいます。
前提
- サーバ側は画面側のどのDOMによって発行されたAjaxリクエストなのかを知ることができない。
上記のような前提があるため予め画面側にはどの行の処理なのかIDを知らせておく必要があります。
メリット
- テンプレートやヘルパーやモデル等のサーバー側で実装した処理を使えて手軽に実装ができる。
- フラグメントキャッシュによる処理の高速化ができる。
デメリット
- 1画面で実装するJavaScriptがあちこちに点在することになるので共通化しずらくなります。
- ES2015でコードを書いておいてWebpackで互換性のあるJSに変換することができないのでES2015が使えない。
この記事へのコメントはありません。