第9回: タスクの完了
2010/05/15
前回は、タスクを追加するアクションを実装しました。
今回は、タスクを完了させる finish アクションを実装します。
ルーティングの修正
エディタで config/routes.rb
を開いて、次のように修正してください。
Nchak::Application.routes.draw do resources :tasks, :only => [ :index, :create ] do put :finish, :on => :member end end
標準の 7 つのアクション(index, show, new, edit, create, update, destroy)以外のアクションを登録するには、do ... end ブロックの内側で get, post, put, delete メソッドを呼びます。これらのメソッドは HTTP メソッドの名前に対応しています。また、これらのメソッドの :on オプションには、アクションが特定の単一レコードを対象とする場合は :member、アクションがレコードの集合を対象とする場合は :collection を指定します。
この修正の結果、/tasks/123/finish
という URL パスに対して PUT メソッドでリクエストすると、tasks コントローラの finish アクションが実行されるようになります。
なお、Rails 2.x では次のように記述していました。
ActionController::Routing::Routes.draw do |map| map.resources :tasks, :only => [ :index, :create ], :member => { :finish => :put } end
あまり変化していないように見えますが、非標準アクションの数が多くなってくると、Rails 3.0 の新しい書き方は大変便利です。
ActionController::Routing::Routes.draw do |map| map.resources :tasks, :only => [ :index, :create ], :member => { :finish => :put, :unfinish => :put }, :collection => { :done => :get } end
と、こんな風に書くより、
Nchak::Application.routes.draw do resources :tasks, :only => [ :index, :create ] do put :finish, :on => :member put :unfinish, :on => :member get :done, :on => :collection end end
の方がすっきりしていますよね。
finish アクションの実装
app/controllers/tasks_controller.rb
を次のように修正します。
class TasksController < ApplicationController (省略) def finish @task = Task.find(params[:id]) @task.update_attribute(:done, true) redirect_to :back end end
まず完了したいタスクを変数 @task に入れ、その done カラムの値を true にセットし、元のページにリダイレクトしています。
HTML テンプレートの修正
app/views/tasks/index.html.erb
を次のように修正します。
(省略) <table class="tasks"> <col class="name" /> <col class="due_date" /> <col class="commands" /> <%= render @tasks %> </table>
app/views/tasks/_task.html.erb
を次のように修正します。
<tr> <td><%= task.name %></td> <td><%= task.due_date %></td> <td><%= link_to '完了', [ :finish, task ], :method => :put %></td> </tr>
link_to はハイパーリンク(つまり、a タグ)を生成するメソッドですが、:method オプションを指定すると GET 以外の HTTP メソッドでブラウザにアクセスさせることができます。
この書き方は Rails 2.x から変化していませんが、生成される HTML コードの形は大きく変化しています。Rails 2.x では、やや長い JavaScript コードが HTML コードの中に埋め込まれていました。
しかし、Rails 3.0 では、次のように単なる a タグが生成されます。
<a href="/tasks/1/finish" data-method="put" rel="nofollow">完了</a>
この a タグがちゃんと「動く」のは、Rails 3.0 で導入された /public/javascripts/rails.js
が存在するためです。JavaScript に詳しい方は、中身を覗いてみると面白いでしょう。
ブラウザで動作確認
タスク一覧ページを開き直します。
「Task 1」の「完了」リンクをクリックします。
done の値が true になったタスクは一覧から消えています。