#Ruby on Rails速習実践ガイド chapter8
##8-2 AjaxでRailsサーバと通信する
Ajax:webブラウザ上で非同期通信を行い、ページの再読み込みなしにページを更新するためのJavascriptのプログラミング手法。
普段はページを更新するのもサーバーからリクエストをもらい少しだけ変わったページであろうとページの全ての部分を読み込み、毎回1から表示していたがAjaxを使えば部分だけを動的に処理しあとはサーバーにも介さずそのままページを使うというもの
今回はタスクを削除する処理をAjaxを用いて処理していく。
Ajaxの処理で行う動作は主に2つある。
①タスクを削除する操作。
②削除したタスクが反映された一覧画面を表示する操作。
この2つのコードを書く。
①のタスクを削除する。だがこれはサーバーがないと何もできないのでAjaxを用いてサーバーを使う。
①のタスクを削除するには、❶Ajaxを使い削除アクションにビューから飛ぶようにして、❷削除アクションをAjax用に書き換えるということをしないといけない
❶Ajaxで削除アクションへリンクを飛ばす方法
変更前のコード
=link_to '削除', task, method: :delete, data:{confirm: "タスク「#{task.name}」を削除します。よろしいですか?"},class: 'btn btn-danger'
変更後のコード
=link_to '削除', task, method: :delete, remote: true, data:{confirm: "タスク「#{task.name}」を削除します。よろしいですか?"},class: 'btn btn-danger'
Ajax機能を使うにはremote: trueと入れるだけ。
❷削除アクションをAjax用に書き換える
変更前のコード
def destroy
@task.destroy
redirect_to tasks_url, notice: "タスク「#{@task.name}」を削除しました"
end
変更後のコード
def destroy
@task.destroy
head :no_content
end
コントローラーの操作でわざわざサーバーを介する必要がない物をAjaxに置き換えると良い。今回はredirect_toメソッドを置き換えた。redirect_toメソッドは一度サーバーを経由してブラウザに反映させるようなルートを通るのでそこをAjaxで経由せずに反映させるようにした。head :no_contentを代わりに書くことでサーバーを経由しなくても削除の成功というレスポンスがくるようになっている。
②削除したタスクが反映された一覧画面を表示する操作。
イベントハンドラという物を使って一覧画面を操作する。イベントハンドラとは何かきっかけが来た時にそれを受け取り何か処理を行う仲介役的な立場。
まずイベントハンドラの対象となるきっかけを見ただけでわかりやすくするためにdeleteクラスをつける。
=link_to '削除', task, method: :delete, remote: true, data:{confirm: "タスク「#{task.name}」を削除します。よろしいですか?"},class: 'btn btn-danger delete'
そしてdeleteクラスを使ってイベントハンドラと実行する行動を書く
document.addEventListener('turbolinks:load', function(){
document.querySelectorAll('.delete').forEach(function(a){
a.addEventListener('ajax:success', function(){
var td = a.parentNode;
var tr = td.parentNode;
tr.style.display = 'none';
});
});
});
##8-2-3 コントローラーからJavascriptを返して実行する
上記ではサーバーでタスクを削除し、用意していたイベントハンドラのなかのJavascriptによってビューを変更した。しかし同じ結果になる操作がもう1パターンある。
ブラウザからサーバーへ「削除してください」という情報を渡し、今回はサーバーがJavascriptを含んだレスポンスを返す方法。(SJRという)削除されたタスクをサーバーはid要素で判断し、レスポンスの時に「そのidのタスクを消す」というJavascriptの操作を返す形となる。
サーバーがどのタスクが削除されたか把握するためにまず専用のid要素をつける
table.table.table-default
...
tbody
- @task.each do |task|
tr id="task-#{task.id}"
td= link_to task.name, task
...
id="task-#{task.id}"という専用のid要素を作った。
destroyアクションに対応するファイルapp/views/tasks/destroy.js.erbを作成してそこにサーバーから欲しいjsの操作を書く。
document.querySelector("#task-<%= @task.id%>").style.display = 'none'
これでサーバーからのレスポンスの時にjsの操作が一緒についてくる
最後にdestroyアクションのredirect_toを消す
def destroy
@task.destroy
end
##8-3 Turbolinks
turbolinks:全てのリンククリックに対するページ遷移を自動的にAjax化することで高速化をはかったもの
##8-4-2-2 コンパイルの実行
コンパイル:コンピュータが実行できるファイル等はコンピュータが理解しやすいように言語化されている。それは人間が見てもわからない。しかしそのファイルは人間が作らなければならない。その時にまず初めに人間が理解できる言語でファイルを作りそれをコンピュータが理解しやすい言語に自動的に変えてくれる作業をしなければなならない。その操作をコンパイルを呼ぶ