【rails】非同期通信でタスクステータスを更新する その2【JQuery】
本日は前回導入した非同期通信をもうちょっと改良したいと思います。
前回の記事は以下です。
前回実装したのは「ボタンを押下するとタスクが完了する」でした。
今回はこの機能をもう拡張して以下のようなボタンにします。
- Done(完了)の時はWIP(継続中)に変更
- それ以外の時はDone(完了)に変更
これで完了したと思ったけど、継続中に戻したい時もボタン一つで対応できます。
それはお品書きです。
- 部分テンプレートを追加、修正
- TaskController、routeを修正
- js.erbを追加、修正
1.部分テンプレートを追加、修正
部分テンプレートを追加、修正します。まずは、app/views/done_wipに_done_wip.html.erbを作成します。フォルダも新しく作成します。
_done_wip.html.erb
<% if task.status == "Done" %> <%= button_to 'WIP', wip_path(task), method: :post, remote: true %> <% else %> <%= button_to 'Done', done_path(task), method: :post, remote: true %> <% end %>
ステータスがDoneの時はWIPアクションを起動するボタンを表示し、それ以外の時はDoneアクションを起動するボタンを表示します。
ステータスをWIPへ更新するアクションやそのルートは後から追加します。
次にapp/views/tasks/_task.html.erbを修正します。
_task.html.erb
<tr> #省略 <% if user_signed_in? && task.user.id == current_user.id %> <td><%= link_to 'Edit', edit_task_path(task) %></td> <td><%= link_to 'Destroy', task, method: :delete, data: { confirm: 'Are you sure?' } %></td>
#button_toの部分を修正 <td id="button<%= task.id %>"><%= render 'done_wip/done_wip', task: task %></td> <% end %> </tr>
これまでbutton_toと記述していた箇所を先ほど作成した部分テンプレート(_done_wip.html.erb)で表示させるように記述を変更します。
またidをbutton<%= task.id %>とすることで、後からJQueryで特定できるようにしておきます。
2.TaskController、routeの修正
次にTaskControllerにWIPアクションを追加します。修正するのはapp/controllers/tasks_controller.rbです。
tasks_controller.rb
class TasksController < ApplicationController before_action :set_task, only: [:show, :edit, :update, :destroy, :done, :wip]
#省略 def wip @task.update(status: "WIP") @tasks = Task.all.includes(:user) end
#省略
end
def doneとほぼ同様なアクションとしてdef wipを追加します。
またset_taskに:wipを追加し、アクション起動前に@taskにタスク一覧画面から送信されてきたidの対応するtask情報を格納できるようにしておきます。
次にルートの設定です。修正するのはconfig/routes.rbです。
Rails.application.routes.draw do #省略 post '/tasks/:id/wip' => 'tasks#wip', as: 'wip' end
今回追加したwipアクションへのルートを記述します。doneアクションの時とほとんど同じです。
3.js.erbの追加、修正
次にwipメソッドに対応したwip.js.erbを作成します。場所はapp/views/tasks/wip.js.erbになります。
wip.js.erb
$('#task<%= @task.id %>').text('WIP'); $('#button<%= @task.id %>').html('<%= escape_javascript(render("done_wip/done_wip", task: @task )) %>')
一行目は前回と同様で、タスクのステータスを変更させる処理です。
二行目は今回作成した_done_wip.html.erbをレンダリングすることで、ボタンをWIPへのリンクからDoneへのリンクに変更させています。
またescape_jacascriptメソッドで特殊文字をエスケープ させています。以下のページにわかりやすく定時されています。
RailsのJavaScript文字列エスケープ – yohgaki's blog
最後にdone.js.erbも修正します。修正するファイルはapp/views/tasks/done.js.erbです。
done.js.erb
$('#task<%= @task.id %>').text('Done'); $('#button<%= @task.id %>').html('<%= escape_javascript(render("done_wip/done_wip", task: @task )) %>')
ボタンをレンダリングする処理を追加しています。
おつかれさまでした、これでタスクを完了させたり、継続中に戻したりするボタンが完成しました。