もこたんぺ Learning Note

自分が勉強する上でわからなかったことを理解を深めていくためにまとめていく。

Ajaxを使ってRailsサーバと通信

AjaxJavaScriptで表現したいことで、サーバ側からデータを新たに取得したり、データを裏側で更新したい時などに使用する。

Ajaxとは

Webブラウザ上で非同期通信を行い、ページの再読み込みなしに、ページを更新するためのJavaScriptのプログラミング手法。

Ajaxを使うことで、ページの一部だけをサーバから取得して、更新することが可能になる。

しかもこの処理は非同期に、バックグラウンドで行われるため、ユーザはページに比べて遷移待ちのストレスが発生しないので、スムーズに操作できる。


Ajaxを使ってタスクを削除したい場合

app/controllers/tasks_controller.rb

def destroy
  @task.destroy
  redirect_to tasks_url, notice: "タスク「#{@task.name}」を削除しました。"
end

削除機能としてやりたいことは以下の2つ

1. タスクを削除する
2. タスクが削除されたことを反映した一覧画面を表示する(削除した)

上記の実装は、ブラウザからPOSTリクエストを送ることで実現している。

これを以下のように変更する。

1. タスクの削除は、サーバサイドでやる必要があるものの、今表示しているタスク一覧画面をそのまま表示し続けていたいため、Ajaxでサーバにリクエストを飛ばす。
2. 次に削除されたタスクの非表示は、クライアントサイドにて、JavaScriptで行う。一つの処理が無事に行われたら非表示になるようにする。

やりたいこととしては、ページを遷移させるのではなく、Ajaxリクエストを発生させる


app/views/tasks/index.html.slim

= link_to '削除', task, nethod: :delete, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

mehod: :deleteを指定してリンクを出力する方法はJavaScriptを介しているが、HTMLのformを使ってリクエストを飛ばしていることと同じなので、ブラウザからrequestを発生させて、ページ遷移している。

Ajaxで削除アクションへリクエストを飛ばすにはremote: trueを追記する。


app/views/tasks/index.html.slim

= link_to '削除', task, nethod: :delete, remote: true, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

RailsAjax機能はこのremote: true属性を見て処理を実行するようになっている。

form_withメソッドはデフォルトでAjax機能を利用していて、無効にする場合はremote: trueオプションを追記する。

次にタスクはサーバサイドで削除して、一覧画面の再表示は必要ないので、

redirect_toの行を削除して、代わりにheadメソッドを用いてレスポンスボディなしでHTTPステータスとして204(成功と判定されること)が返るようにしておく。


app/controllers/tasks_controller.rb

def destroy
  @task.destroy
  head :no_content
end

この状態で削除を行なっても、画面はそのままになってしまう。

なので削除したら、削除したタスクを非表示する処理をJavaScriptを実装する。

Railsremote: trueをつけたa要素に対して、Ajax通信が成功したときにajax:successというイベントを発行してくれる。

そこでこれに対応するイベントハンドラを記述する。

対象となるa要素を簡単に特定できるようにしたいので、まずは削除リンクのa要素に「delete」というCSSクラスを目印として付与する。


app/views/tasks/index.html.slim

= link_to '削除', task, nethod: :delete, remote: true, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger delete'

次に、app/assets/javascripts/task.jsでこの目印を利用して、削除リンク(a要素)にイベントハンドラを設定する。


参考

Rails で JavaScript を使用する - Railsガイド

Ruby on Rails - RailsでJavaScriptを使う - このガイドでは、Railsに組み込まれたAjax/JavaScriptの機能(およびそれ以上の機能)をカバーしていますので、リッチでダイナミックなAjaxアプリ - 日本語