【rails】非同期通信でタスクステータスを変更する【JQuery】
本日は非同期通信でタスクステータスを「Done(タスク完了)」に変更する機能を実装しようと思います。
「非同期通信」というのがポイント。
非同期通信とは、簡単に説明すると「ページ遷移させずにデータを取得してページの一部を変更する」ことを言います。
非同期通信のメリットは、素早く、スムーズな表示の変更が可能になります。
以前作成したタスクステータス完了ボタンはtasksテーブルのstatusカラムを「done」で更新したあと、タスク一覧画面(index.html.erb)を再表示させていました。
非同期通信を利用することで、ページを再読み込みせず、タスクステータス表示を変更させていきます。
本日のお品書き
- ボタンの変更
- js.erbの追加
1.ボタンの変更
まずはボタンの変更から行います。修正するファイルはapp/views/tasks/_task.html.erbです。
_task.html.erb
<tr> #省略
<td id="task<%= task.id %>" ><%= task.status %></td>
#省略 <% if user_signed_in? && task.user.id == current_user.id %> #省略 <td><%= button_to 'Done', done_path(task), method: :post, remote: true %></td> <% end %> </tr>
button_toにremote: tureを追加します。このオプションを追加することで非同期通信が可能になります。
またid="task<%= task.id %>"とすることで、例えばtask.idが6であれば、id=task6となり、後からidをキーにstatusの変更することが可能となります。
2.done.js.erbの追加
続いて非同期通信でタスク一覧画面の表示を変更するためにdone.js.erbを追加します。追加するフォルダはapp/views/tasksです。
ちなみにファイル名はアクション名.js.erbとする規則があります。
done.js.erb
$('#task<%= @task.id %>').text('Done');
非常にシンプルです。先ほど追加したidを探しにいき、値を「Done」に更新しています。
最後にdoneアクションを修正します。ファイルはapp/controllers/tasks_controller.rbです。
tasks_controller.rb
def done @task.update(status: "Done") @tasks = Task.all.includes(:user)
#render :index #ここを削除 end
render :indexを削除します。この部分がindexアクションに対応するページ、すなわちタスク一覧ページを表示させる(レンダリング)処理になります。
非同期通信ではページを再度表示させることはしないので削除するわけです。
これまでの通信と非同期通信との違い
これまでlink_toやbutton_toで通信してきたものと今回の非同期通信では以下のような違いがあります。
これまでの通信
- html形式でリクエストを送る
- URLからルーターがコントローラとアクションを決める(TasksControllerのdoneアクション)
- アクションを実行後、指定されたページを表示させる(index.html.erb)
非同期通信
- js形式でリクエストを送る
- URLからルーターがコントローラとアクションを決める(TasksControllerのdoneアクション)
- アクションを実行後、アクション名.js.erbを実行する(done.js.erb)
通信形式が異なることについてはここでは詳しく解説しません。大事なのは3番目のページ(index.html.erb)を再度表示させるか、done.js.erbを実行するかの違いです。
done.js.erbはページ全体を再度表示させるのではなく、変更した一部のみを対象に更新しています。
お疲れ様でした。以上で非同期通信でタスクステータスを変更するは終了です。
次回はまた非同期通信を使って、タスクをdone(完了)↔︎WIP(実施中)と変更できるようにしようと思います。
あとがき
プログラミングスクールで学習した方法(ajaxとjbuilder)を使ってやろうとしたんだけどうまくいかなかった、より簡単な方法に変更しました。うまくいかなかった原因を特定してまた紹介したいと思います。