STEP 10: finishアクションの実装

2010/02/13

今回は、タスク一覧ページにある「完了」リンクを実装します。

このリンクをクリックすると、done カラムの値が true になり、タスクが完了したことになります。


まず、ルーティングを修正します。

$ edit config/routes.rb
ActionController::Routing::Routes.draw do |map|
  map.root :controller => 'top', :action => 'index'

  map.resources :tasks,
    :member => { :simple => :get, :finish => :put },
    :collection => { :unfinished => :get }
end

5行目の :member オプションの値に :finish => :put という要素を追加しています。

この finish アクションは、特定のレコードの中身を変化させます。そのような場合は、PUTメソッドを利用します。


次に、finish アクションを実装します。

$ edit app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  (省略)

  def finish
    @task = Task.find(params[:id])
    @task.update_attribute(:done, true)
    redirect_to :tasks
  end

  def destroy
  (省略)
end

特定のタスクの done カラムを true にセットし、タスク一覧ページにリダイレクトしています。


ヘルパー operations_on_task を修正します。

$ edit app/helpers/tasks_helper.rb
module TasksHelper
  def operations_on_task(task)
    links = []
    links << link_to('簡易表示', [ :simple, task ])
    links << link_to('編集', [ :edit, task ])
    if task.done?
      links << content_tag(:span, '完了', :class => 'disabled')
    else
      links << link_to('完了', [ :finish, task ], :method => :put)
    end
    links << link_to('削除', task, :method => :delete,
      :confirm => '本当に削除しますか?')
    links.join(' | ')
  end
end

7行目では content_tag メソッドを使って span 要素を生成しています。直接的に文字列で links &;&; "&;span class='disabled'&;完了&;/span&;" のように記述しても構わないのですが、私は content_tag メソッドを好んで利用します。現状では span 要素の class 属性に 'disabled' という固定値を指定していますが、式を使って動的に指定したくなるかもしれません。その場合、"&;span class='#{式}'&;完了&;/span&;" のように式を埋め込むよりも、content_tag(:span, '完了', :class => 式) と書いた方が読みやすくなります。

スタイルシートを修正します。

$ edit public/stylesheets/application.css
a:visited {
  color: blue;
}

span.disabled {
  color: #888;
}

(省略)

ブラウザでタスク一覧ページを表示して、適当なタスクの「完了」リンクをクリックすると、完了カラムの値が「Yes」に変化します。

画面キャプチャ1