You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by as...@apache.org on 2008/05/29 01:02:16 UTC

svn commit: r661136 - in /ode/sandbox/singleshot: app/helpers/ app/models/ app/views/tasks/ db/ db/migrate/ lib/tasks/ public/stylesheets/ spec/ spec/models/

Author: assaf
Date: Wed May 28 16:02:15 2008
New Revision: 661136

URL: http://svn.apache.org/viewvc?rev=661136&view=rev
Log:
Added form_perform_url and form_view_url, both of which are optional (not all tasks have forms).
Added form_completing which decides whether form completes task, or we need to include a button to mark task as completed.

Modified:
    ode/sandbox/singleshot/app/helpers/task_helper.rb
    ode/sandbox/singleshot/app/models/task.rb
    ode/sandbox/singleshot/app/views/tasks/show.html.erb
    ode/sandbox/singleshot/db/migrate/20080506015046_create_tasks.rb
    ode/sandbox/singleshot/db/schema.rb
    ode/sandbox/singleshot/lib/tasks/populate.rake
    ode/sandbox/singleshot/public/stylesheets/default.css
    ode/sandbox/singleshot/spec/common.rb
    ode/sandbox/singleshot/spec/models/task_spec.rb

Modified: ode/sandbox/singleshot/app/helpers/task_helper.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/helpers/task_helper.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/helpers/task_helper.rb (original)
+++ ode/sandbox/singleshot/app/helpers/task_helper.rb Wed May 28 16:02:15 2008
@@ -15,12 +15,15 @@
     vitals.to_sentence
   end
 
-  def task_iframe_url(task, person = authenticated)
-    task_uri = URI(task_perform_url(task))
-    task_uri.user, task_uri.password = '_token', task.token_for(person)
-    uri = URI(task.frame_url)
-    uri.query = CGI.parse(uri.query || '').update('perform'=>task.owner?(person), 'task_url'=>task_uri).to_query
-    uri.to_s
+  def task_frame(task)
+    if task.form_perform_url
+      task_uri = URI(task_perform_url(task))
+      task_uri.user, task_uri.password = '_token', task.token_for(authenticated)
+      uri = URI(task.owner?(authenticated) ? task.form_perform_url : (task.form_view_url || task.form_perform_url)) 
+      uri.query = CGI.parse(uri.query || '').update('perform'=>task.owner?(authenticated), 'task_url'=>task_uri).to_query
+      uri.to_s
+      content_tag 'iframe', '', :id=>'task_frame', :src=>uri.to_s
+    end
   end
 
 end

Modified: ode/sandbox/singleshot/app/models/task.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/task.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/task.rb (original)
+++ ode/sandbox/singleshot/app/models/task.rb Wed May 28 16:02:15 2008
@@ -3,20 +3,22 @@
 #
 # Table name: tasks
 #
-#  id           :integer         not null, primary key
-#  title        :string(255)     not null
-#  description  :string(255)     not null
-#  priority     :integer(1)      not null
-#  due_on       :date
-#  status       :string(255)     not null
-#  frame_url    :string(255)
-#  outcome_url  :string(255)
-#  outcome_type :string(255)
-#  access_key   :string(32)
-#  data         :text            not null
-#  version      :integer         default(0), not null
-#  created_at   :datetime
-#  updated_at   :datetime
+#  id               :integer         not null, primary key
+#  title            :string(255)     not null
+#  description      :string(255)     not null
+#  priority         :integer(1)      not null
+#  due_on           :date
+#  status           :string(255)     not null
+#  form_view_url    :string(255)
+#  form_perform_url :string(255)
+#  form_completing  :boolean
+#  outcome_url      :string(255)
+#  outcome_type     :string(255)
+#  access_key       :string(32)
+#  data             :text            not null
+#  version          :integer         default(0), not null
+#  created_at       :datetime
+#  updated_at       :datetime
 #
 
 require 'openssl'
@@ -107,28 +109,32 @@
 
 
   # -- Common task attributes --
-  #
 
-  validates_presence_of :title, :frame_url
-  validates_url :frame_url, :if=>:frame_url
+  validates_presence_of :title
 
-  # -- View and perform ---
 
+  # -- View and perform ---
 
-  # --- Task data ---
+  validates_url :form_perform_url, :if=>:form_perform_url
+  validates_url :form_view_url, :if=>:form_view_url
 
-  def data
-    return self[:data] if Hash === self[:data]
-    self[:data] = ActiveSupport::JSON.decode(self[:data] || '')
+  before_validation do |record|
+    unless record.form_perform_url
+      record.form_view_url = nil 
+      record.form_completing = nil
+    end
   end
 
-  def data=(data)
-    raise ArgumentError, 'Must be a hash or nil' unless Hash === data || data.nil?
-    self[:data] = data || {}
+
+  # --- Task data ---
+
+  serialize :data
+  before_validation do |record|
+    record.data ||= {}
   end
 
-  before_save do |task|
-    task[:data] = task[:data].to_json if task[:data]
+  validate do |record|
+    record.errors.add :data, 'Must be a hash' unless Hash === record.data
   end
 
 
@@ -163,7 +169,7 @@
   end
 
   def over_due?
-    due_on && due_on < Date.today
+    due_on ? due_on < Date.today : false
   end
 
   # Scopes can use this to add ranking methods on returned records.

Modified: ode/sandbox/singleshot/app/views/tasks/show.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/tasks/show.html.erb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/tasks/show.html.erb (original)
+++ ode/sandbox/singleshot/app/views/tasks/show.html.erb Wed May 28 16:02:15 2008
@@ -1,42 +1,44 @@
 <% div_for @task do %>
   <div class='bar'>
     <div class='summary'>
-    <div class='vitals'><%= task_vitals(@task) %></div>
-    <div class='actions'><%= quick_actions(@task) %> <%= content_tag 'button', '▽ More Options', :onclick=>"Singleshot.expand(event, '.expanded', '△ Less options')", :class=>'button-to' %></div>
-  </div>
-  <div class='expanded' style='display:none'>
-    <%= link_to image_tag('calendar.png') + ' Calendar', formatted_task_url(@task, 'ics', :access_key=>authenticated.access_key),
-        :rel=>'alternate', :title=>'Add this task to your calendar' %>
-    <%= link_to image_tag('feed.png') + ' Activity', formatted_activity_url(@task, 'atom', :access_key=>authenticated.access_key),
-        :rel=>'alternate', :title=>'Subscribe to see changes to this task' %>
-    <h2><%= h(@task.title) %></h2>
-    <div class='description'><%= sanitize(simple_format(@task.description)) %></div>
-    <dl>
-      <dt>Priority</dt><dd><%= ['High', 'Medium', 'Low'][@task.priority - 1] %></dd>
-      <%= content_tag('dt', 'Due on') + content_tag('dd', relative_date(@task.due_on)) if @task.due_on %>
-      <dt>Recent activity</dt>
-      <dd>
-        <ol class='activities hfeed'>
-          <% for activity in @task.activities %>
-            <% content_tag_for 'li', activity, :class=>'hentry entry-title' do %>
-              <%= link_to activity.person.fullname, activity.person.identity %>
-              <%= activity.action %>
-              <%= link_to activity.task.title, task_url(activity.task), :rel=>'bookmark' %>
+      <div class='vitals'><%= task_vitals(@task) %></div>
+      <div class='actions'><%= quick_actions(@task) %> <%= content_tag 'button', '▽ More Options', :onclick=>"Singleshot.expand(event, '.expanded', '△ Less options')", :class=>'button-to' %></div>
+    </div>
+    <div class='expanded' style='display:none'>
+      <%= link_to image_tag('calendar.png') + ' Calendar', formatted_task_url(@task, 'ics', :access_key=>authenticated.access_key),
+          :rel=>'alternate', :title=>'Add this task to your calendar' %>
+      <%= link_to image_tag('feed.png') + ' Activity', formatted_activity_url(@task, 'atom', :access_key=>authenticated.access_key),
+          :rel=>'alternate', :title=>'Subscribe to see changes to this task' %>
+      <h2><%= h(@task.title) %></h2>
+      <dl>
+        <dt>Priority</dt><dd><%= ['High', 'Medium', 'Low'][@task.priority - 1] %></dd>
+        <%= content_tag('dt', 'Due on') + content_tag('dd', relative_date(@task.due_on)) if @task.due_on %>
+        <dt>Recent activity</dt>
+        <dd>
+          <ol class='activities hfeed'>
+            <% for activity in @task.activities %>
+              <% content_tag_for 'li', activity, :class=>'hentry entry-title' do %>
+                <%= link_to activity.person.fullname, activity.person.identity %>
+                <%= activity.action %>
+                <%= link_to activity.task.title, task_url(activity.task), :rel=>'bookmark' %>
+              <% end %>
             <% end %>
-          <% end %>
-        </ol>
-      </dd>
-      <%= admins = @task.admins.map { |person| link_to_person(person, :admin) }
-          content_tag('dt', 'Admins') + content_tag('dd', admins.to_sentence) unless admins.empty? %>
-      <%= observers = @task.observers.map { |person| link_to_person(person, :observer) }
-          content_tag('dt', 'Observers') + content_tag('dd', observers.to_sentence) unless observers.empty? %>
-    </dl>
-    <div class='actions'>
-      <%= quick_actions(@task) %>
+          </ol>
+        </dd>
+        <%= admins = @task.admins.map { |person| link_to_person(person, :admin) }
+            content_tag('dt', 'Admins') + content_tag('dd', admins.to_sentence) unless admins.empty? %>
+        <%= observers = @task.observers.map { |person| link_to_person(person, :observer) }
+            content_tag('dt', 'Observers') + content_tag('dd', observers.to_sentence) unless observers.empty? %>
+      </dl>
+      <div class='actions'>
+        <%= quick_actions(@task) %>
+      </div>
     </div>
   </div>
-
-  </div>
-  <%= content_tag 'iframe', nil, :id=>'task_frame', :src=>task_iframe_url(@task) %>
+  <div class='description'><%= sanitize(simple_format(@task.description)) %></div>
+  <%= task_frame @task %>
+  <% unless @task.form_completing %>
+    <div class='completion'><div class='actions'><%= button_to 'Completed', task_url(@task, :status=>'completed'), :title=>'Click when task completed' %></div></div>
+  <% end %>
   <%= javascript_tag 'Singleshot.taskView()' %>
 <% end %>

Modified: ode/sandbox/singleshot/db/migrate/20080506015046_create_tasks.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/db/migrate/20080506015046_create_tasks.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/db/migrate/20080506015046_create_tasks.rb (original)
+++ ode/sandbox/singleshot/db/migrate/20080506015046_create_tasks.rb Wed May 28 16:02:15 2008
@@ -6,7 +6,9 @@
       t.integer   'priority',     :null=>false, :limit=>1
       t.date      'due_on',       :null=>true
       t.string    'status',       :null=>false
-      t.string    'frame_url',    :null=>true
+      t.string    'form_view_url'
+      t.string    'form_perform_url'
+      t.boolean   'form_completing'
       t.string    'outcome_url',  :null=>true
       t.string    'outcome_type', :null=>true
       t.string    'access_key',   :null=>true, :limit=>32

Modified: ode/sandbox/singleshot/db/schema.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/db/schema.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/db/schema.rb (original)
+++ ode/sandbox/singleshot/db/schema.rb Wed May 28 16:02:15 2008
@@ -43,17 +43,19 @@
   end
 
   create_table "tasks", :force => true do |t|
-    t.string   "title",                                     :null => false
-    t.string   "description",                               :null => false
-    t.integer  "priority",     :limit => 1,                 :null => false
+    t.string   "title",                                         :null => false
+    t.string   "description",                                   :null => false
+    t.integer  "priority",         :limit => 1,                 :null => false
     t.date     "due_on"
-    t.string   "status",                                    :null => false
-    t.string   "frame_url"
+    t.string   "status",                                        :null => false
+    t.string   "form_view_url"
+    t.string   "form_perform_url"
+    t.boolean  "form_completing"
     t.string   "outcome_url"
     t.string   "outcome_type"
-    t.string   "access_key",   :limit => 32
-    t.text     "data",                                      :null => false
-    t.integer  "version",                    :default => 0, :null => false
+    t.string   "access_key",       :limit => 32
+    t.text     "data",                                          :null => false
+    t.integer  "version",                        :default => 0, :null => false
     t.datetime "created_at"
     t.datetime "updated_at"
   end

Modified: ode/sandbox/singleshot/lib/tasks/populate.rake
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/lib/tasks/populate.rake?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/lib/tasks/populate.rake (original)
+++ ode/sandbox/singleshot/lib/tasks/populate.rake Wed May 28 16:02:15 2008
@@ -36,7 +36,7 @@
       retract 
       you = Person.find_by_identity(ENV['USER']) 
       defaults = { :title=>Faker::Lorem.sentence, :description=>Faker::Lorem.paragraphs(3).join("\n\n"),
-                   :frame_url=>'http://localhost:3001/sandwich', :potential_owners=>[you, other] }
+                   :form_perform_url=>'http://localhost:3001/sandwich', :form_completing=>true, :potential_owners=>[you, other] }
       returning Task.new(defaults.merge(attributes || {})) do |task|
         task.modified_by(you).save!
       end

Modified: ode/sandbox/singleshot/public/stylesheets/default.css
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/public/stylesheets/default.css?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/public/stylesheets/default.css (original)
+++ ode/sandbox/singleshot/public/stylesheets/default.css Wed May 28 16:02:15 2008
@@ -316,9 +316,6 @@
   font-size: 1.2em;
   margin: 0 0 1em 0;
 }
-div.task div.bar div.expanded div.description {
-  margin: 1em 0 1em 0;
-}
 div.task div.bar div.expanded dl {
 }
 div.task div.bar div.expanded dt {
@@ -337,12 +334,16 @@
   text-align: right;
 }
 
+div.task div.description {
+  padding: 3em 3em 1em 3em;
+}
+
 div.task iframe {
   border: 0;
   width: 100%;
   height: 0;
   padding: 0;
-  margin: 3em 0 0 0;
+  margin: 0;
   background: transparent;
 }
 

Modified: ode/sandbox/singleshot/spec/common.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/common.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/common.rb (original)
+++ ode/sandbox/singleshot/spec/common.rb Wed May 28 16:02:15 2008
@@ -51,7 +51,6 @@
 
     def default_task(with = {})
       { :title=>'Test this',
-        :frame_url=>'http://test.host/fill_me',
         :outcome_url=>'http://test.host/outcome' }.merge(with)
     end
 

Modified: ode/sandbox/singleshot/spec/models/task_spec.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/models/task_spec.rb?rev=661136&r1=661135&r2=661136&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/models/task_spec.rb (original)
+++ ode/sandbox/singleshot/spec/models/task_spec.rb Wed May 28 16:02:15 2008
@@ -1,285 +1,363 @@
 require File.dirname(__FILE__) + '/../spec_helper'
 
 
-describe Task, 'to_param' do
+describe Task do
   include Specs::Tasks
 
-  it 'should return nil unless task exists in database' do
-    Task.new.to_param.should be_nil
-  end
+  describe 'to_param' do
 
-  it 'should begin with task ID' do
-    Task.create!(default_task).to_param.to_i.should == Task.last.id
-  end
+    it 'should return nil unless task exists in database' do
+      Task.new.to_param.should be_nil
+    end
 
-  it 'should include task title' do
-    Task.create!(default_task.merge(:title=>'Task Title')).to_param[/^\d+-(.*)/, 1].should == 'Task-Title'
-  end
+    it 'should begin with task ID' do
+      Task.create!(default_task).to_param.to_i.should == Task.last.id
+    end
 
-  it 'should properly encode task title' do
-    Task.create!(default_task.merge(:title=>'Test:encoding, ignoring "unprintable" characters')).
-      to_param[/^\d+-(.*)/, 1].should == 'Test-encoding-ignoring-unprintable-characters'
-  end
+    it 'should include task title' do
+      Task.create!(default_task.merge(:title=>'Task Title')).to_param[/^\d+-(.*)/, 1].should == 'Task-Title'
+    end
 
-  it 'should remove redundant hyphens' do
-    Task.create!(default_task.merge(:title=>'-Test  redundant--hyphens--')).to_param[/^\d+-(.*)/, 1].should == 'Test-redundant-hyphens'
-  end
+    it 'should properly encode task title' do
+      Task.create!(default_task.merge(:title=>'Test:encoding, ignoring "unprintable" characters')).
+        to_param[/^\d+-(.*)/, 1].should == 'Test-encoding-ignoring-unprintable-characters'
+    end
 
-  it 'should deal gracefully with missing title' do
-    Task.create!(default_task.merge(:title=>'--')).to_param.should =~ /^\d+$/
-  end
+    it 'should remove redundant hyphens' do
+      Task.create!(default_task.merge(:title=>'-Test  redundant--hyphens--')).to_param[/^\d+-(.*)/, 1].should == 'Test-redundant-hyphens'
+    end
+
+    it 'should deal gracefully with missing title' do
+      Task.create!(default_task.merge(:title=>'--')).to_param.should =~ /^\d+$/
+    end
+
+    it 'should leave UTF-8 text alone' do
+      Task.create!(default_task.merge(:title=>'jösé')).to_param[/^\d+-(.*)/, 1].should == 'jösé'
+    end
 
-  it 'should leave UTF-8 text alone' do
-    Task.create!(default_task.merge(:title=>'jösé')).to_param[/^\d+-(.*)/, 1].should == 'jösé'
   end
 
-end
 
+  describe 'version' do
 
-describe Task, 'version' do
-  include Specs::Tasks
+    it 'should begin at zero' do
+      Task.create!(default_task).version.should == 0 
+    end
 
-  it 'should begin at zero' do
-    Task.create!(default_task).version.should == 0 
+    it 'should increment each time task is updated' do
+      Task.create! default_task
+      lambda { Task.last.update_attributes :priority=>1 }.should change { Task.last.version }.from(0).to(1)
+      lambda { Task.last.update_attributes :due_on=>Time.now }.should change { Task.last.version }.from(1).to(2)
+    end
   end
 
-  it 'should increment each time task is updated' do
-    Task.create! default_task
-    lambda { Task.last.update_attributes :priority=>1 }.should change { Task.last.version }.from(0).to(1)
-    lambda { Task.last.update_attributes :due_on=>Time.now }.should change { Task.last.version }.from(1).to(2)
-  end
-end
 
+  describe 'etag' do
 
-describe Task, 'etag' do
-  include Specs::Tasks
+    it 'should be hex digest' do
+      Task.create!(default_task).etag.should =~ /^[0-9a-f]{32}$/
+    end
 
-  it 'should be hex digest' do
-    Task.create!(default_task).etag.should =~ /^[0-9a-f]{32}$/
-  end
+    it 'should remain the same if task not modified' do
+      Task.create! default_task
+      Task.last.etag.should == Task.last.etag
+    end
 
-  it 'should remain the same if task not modified' do
-    Task.create! default_task
-    Task.last.etag.should == Task.last.etag
-  end
+    it 'should be different for two different tasks' do
+      Task.create!(default_task).etag.should_not == Task.create(default_task).etag
+    end
 
-  it 'should be different for two different tasks' do
-    Task.create!(default_task).etag.should_not == Task.create(default_task).etag
-  end
+    it 'should change whenever task is saved' do
+      Task.create! default_task
+      lambda { Task.last.update_attributes! :priority=>1 }.should change { Task.last.etag }
+      lambda { Task.last.update_attributes! :due_on=>Time.now }.should change { Task.last.etag }
+    end
 
-  it 'should change whenever task is saved' do
-    Task.create! default_task
-    lambda { Task.last.update_attributes! :priority=>1 }.should change { Task.last.etag }
-    lambda { Task.last.update_attributes! :due_on=>Time.now }.should change { Task.last.etag }
   end
 
-end
 
+  describe 'status' do
 
-describe Task, 'status' do
-  include Specs::Tasks
+    def task_with_status(status, attributes = nil)
+      attributes ||= {}
+      task = case status
+      when 'active'
+        Task.create!(default_task.merge(attributes).merge(:status=>status, :owner=>person('owner')))
+      when 'completed'
+        active = Task.create!(default_task.merge(attributes).merge(:status=>'active', :owner=>person('owner')))
+        active.update_attributes :status=>'completed'
+        active
+      else
+        Task.create!(default_task.merge(attributes).merge(:status=>status))
+      end
 
-  def task_with_status(status, attributes = nil)
-    attributes ||= {}
-    task = case status
-    when 'active'
-      Task.create!(default_task.merge(attributes).merge(:status=>status, :owner=>person('owner')))
-    when 'completed'
-      active = Task.create!(default_task.merge(attributes).merge(:status=>'active', :owner=>person('owner')))
-      active.update_attributes :status=>'completed'
-      active
-    else
-      Task.create!(default_task.merge(attributes).merge(:status=>status))
+      def task.transition_to(status, attributes = nil)
+        attributes ||= {}
+        update_attributes attributes.merge(:status=>status)
+        self
+      end
+      def task.can_transition?(status, attributes = nil)
+        transition_to(status, attributes).errors_on(:status).empty?
+      end
+      task
     end
 
-    def task.transition_to(status, attributes = nil)
-      attributes ||= {}
-      update_attributes attributes.merge(:status=>status)
-      self
+    it 'should start as ready' do
+      Task.create!(default_task).status.should == 'ready'
     end
-    def task.can_transition?(status, attributes = nil)
-      transition_to(status, attributes).errors_on(:status).empty?
+
+    it 'should only accept supported value' do
+      Task.create(:status=>'unsupported').should have(1).error_on(:status)
     end
-    task
-  end
 
-  it 'should start as ready' do
-    Task.create!(default_task).status.should == 'ready'
-  end
+    it 'should allow starting in reserved' do
+      Task.create!(default_task.merge(:status=>'reserved')).status.should == 'reserved'
+    end
 
-  it 'should only accept supported value' do
-    Task.create(:status=>'unsupported').should have(1).error_on(:status)
-  end
+    it 'should not transition to reserved from any other status' do
+      for status in Task::STATUSES - ['reserved']
+        task_with_status(status).can_transition?('reserved').should be_false
+      end
+    end
 
-  it 'should allow starting in reserved' do
-    Task.create!(default_task.merge(:status=>'reserved')).status.should == 'reserved'
-  end
+    it 'should start as ready if started as active but not associated with owner' do
+      Task.create!(default_task.merge(:status=>'active')).status.should == 'ready'
+    end
 
-  it 'should not transition to reserved from any other status' do
-    for status in Task::STATUSES - ['reserved']
-      task_with_status(status).can_transition?('reserved').should be_false
+    it 'should start as active if started as ready and associated with owner' do
+      Task.create!(default_task.merge(:owner=>person('owner'))).status.should == 'active'
     end
-  end
 
-  it 'should start as ready if started as active but not associated with owner' do
-    Task.create!(default_task.merge(:status=>'active')).status.should == 'ready'
-  end
+    it 'should start as active if started as ready and associated with one potential owner' do
+      Task.create!(default_task.merge(:potential_owners=>people('owner'))).status.should == 'active'
+    end
 
-  it 'should start as active if started as ready and associated with owner' do
-    Task.create!(default_task.merge(:owner=>person('owner'))).status.should == 'active'
-  end
+    it 'should start as ready if started as ready and associated with several potential owners' do
+      Task.create!(default_task.merge(:potential_owners=>people('foo', 'bar'))).status.should == 'ready'
+    end
 
-  it 'should start as active if started as ready and associated with one potential owner' do
-    Task.create!(default_task.merge(:potential_owners=>people('owner'))).status.should == 'active'
-  end
+    it 'should transition from ready to active when associated with owner' do
+      task = task_with_status('ready')
+      lambda { task.update_attributes :owner=>person('owner') }.should change(task, :status).to('active')
+    end
 
-  it 'should start as ready if started as ready and associated with several potential owners' do
-    Task.create!(default_task.merge(:potential_owners=>people('foo', 'bar'))).status.should == 'ready'
-  end
+    it 'should transition from active to ready when owner removed' do
+      task = task_with_status('active')
+      lambda { task.update_attributes :owner=>nil }.should change(task, :status).to('ready')
+    end
 
-  it 'should transition from ready to active when associated with owner' do
-    task = task_with_status('ready')
-    lambda { task.update_attributes :owner=>person('owner') }.should change(task, :status).to('active')
-  end
+    it 'should accept suspended as initial value' do
+      Task.create!(default_task.merge(:status=>'suspended')).status.should == 'suspended'
+    end
 
-  it 'should transition from active to ready when owner removed' do
-    task = task_with_status('active')
-    lambda { task.update_attributes :owner=>nil }.should change(task, :status).to('ready')
-  end
+    it 'should transition from ready to suspended' do
+      task_with_status('ready').can_transition?('suspended').should be_true
+    end
 
-  it 'should accept suspended as initial value' do
-    Task.create!(default_task.merge(:status=>'suspended')).status.should == 'suspended'
-  end
+    it 'should transition from suspended back to ready' do
+      task_with_status('suspended').transition_to('ready').status.should == 'ready'
+      task_with_status('suspended').transition_to('active').status.should == 'ready'
+    end
 
-  it 'should transition from ready to suspended' do
-    task_with_status('ready').can_transition?('suspended').should be_true
-  end
+    it 'should transition from active to suspended' do
+      task_with_status('active').can_transition?('suspended').should be_true
+    end
 
-  it 'should transition from suspended back to ready' do
-    task_with_status('suspended').transition_to('ready').status.should == 'ready'
-    task_with_status('suspended').transition_to('active').status.should == 'ready'
-  end
+    it 'should transition from suspended back to active' do
+      task_with_status('suspended', :owner=>person('owner')).transition_to('active').status.should == 'active'
+      task_with_status('suspended', :owner=>person('owner')).transition_to('ready').status.should == 'active'
+    end
 
-  it 'should transition from active to suspended' do
-    task_with_status('active').can_transition?('suspended').should be_true
-  end
+    it 'should only transition to completed from active' do
+      for status in Task::STATUSES - ['completed']
+        task_with_status(status).can_transition?('completed').should == (status =='active')
+      end
+    end
 
-  it 'should transition from suspended back to active' do
-    task_with_status('suspended', :owner=>person('owner')).transition_to('active').status.should == 'active'
-    task_with_status('suspended', :owner=>person('owner')).transition_to('ready').status.should == 'active'
-  end
+    it 'should not transition to completed without owner' do
+      task_with_status('active').can_transition?('completed', :owner=>nil).should be_false
+    end
 
-  it 'should only transition to completed from active' do
-    for status in Task::STATUSES - ['completed']
-      task_with_status(status).can_transition?('completed').should == (status =='active')
+    it 'should not transition from completed to any other status' do
+      for status in Task::STATUSES - ['completed']
+        task_with_status('completed').can_transition?(status).should be_false
+      end
     end
-  end
 
-  it 'should not transition to completed without owner' do
-    task_with_status('active').can_transition?('completed', :owner=>nil).should be_false
-  end
+    it 'should transition to cancelled from any other status but completed' do
+      for status in Task::STATUSES - ['cancelled']
+        task_with_status(status).can_transition?('cancelled').should == (status !='completed')
+      end
+    end
 
-  it 'should not transition from completed to any other status' do
-    for status in Task::STATUSES - ['completed']
-      task_with_status('completed').can_transition?(status).should be_false
+    it 'should not transition from cancelled to any other status' do
+      for status in Task::STATUSES - ['cancelled']
+        task_with_status('cancelled').can_transition?(status).should be_false
+      end
     end
-  end
 
-  it 'should transition to cancelled from any other status but completed' do
-    for status in Task::STATUSES - ['cancelled']
-      task_with_status(status).can_transition?('cancelled').should == (status !='completed')
+    it 'should not allow changing of completed or cancelled tasks' do
+      lambda { task_with_status('completed').update_attributes :title=>'never mind' }.should raise_error(ActiveRecord::ReadOnlyRecord)
+      lambda { task_with_status('cancelled').update_attributes :title=>'never mind' }.should raise_error(ActiveRecord::ReadOnlyRecord)
     end
+
   end
 
-  it 'should not transition from cancelled to any other status' do
-    for status in Task::STATUSES - ['cancelled']
-      task_with_status('cancelled').can_transition?(status).should be_false
+
+  describe 'title' do
+
+    it 'should be required' do
+      Task.new(default_task.except(:title)).should have(1).error_on(:title)
+    end
+
+    it 'should not be empty' do
+      Task.new(default_task.merge(:title=>' ')).should have(1).error_on(:title)
     end
-  end
 
-  it 'should not allow changing of completed or cancelled tasks' do
-    lambda { task_with_status('completed').update_attributes :title=>'never mind' }.should raise_error(ActiveRecord::ReadOnlyRecord)
-    lambda { task_with_status('cancelled').update_attributes :title=>'never mind' }.should raise_error(ActiveRecord::ReadOnlyRecord)
   end
 
-end
 
+  describe 'priority' do
 
-=begin
-describe Task, 'priority' do
-  include Specs::Tasks
+    it 'should default to 2' do
+      Task.create(default_task.except(:priority)).priority.should == 2
+    end
 
-  it 'should default to 1' do
-    Task.new.priority.should == 1
-  end
+    it 'should allow values from 1 to 3' do
+      priorities = Array.new(5) { |i| i }
+      priorities.map { |p| Task.new(default_task.merge(:priority=>p)).valid? }.should eql([false] + [true] * 3 + [false])
+    end
 
-  it 'should allow values from 1 to 3' do
-    priorities = Array.new(5) { |i| i }
-    priorities.map { |p| Task.new(default_task.merge(:priority=>p)).valid? }.should eql([false] + [true] * 3 + [false])
-  end
+    it 'should accept string value' do
+      Task.create(default_task.merge(:priority=>'1')).priority.should == 1
+    end
 
-  it 'should accept string value' do
-    Task.create default_task 
-    lambda { Task.first.update_attributes! :priority=>'2' }.should change { Task.first.priority }.to(2)
-  end
+    it 'should accept nil and reset to default' do
+      Task.create default_task.merge(:priority=>1)
+      lambda { Task.last.update_attributes! :priority=>nil }.should change { Task.last.priority }.to(2)
+    end
 
-  it 'should accept nil and reset to default' do
-    Task.create default_task.merge(:priority=>2)
-    lambda { Task.first.update_attributes! :priority=>nil }.should change { Task.first.priority }.to(1)
   end
 
-end
 
+  describe 'high_priority?' do
 
-describe Task, 'title' do
-  include Specs::Tasks
+    it 'should be true for priority 1' do
+      Task.new(:priority=>1).high_priority?.should be_true
+    end
+
+    it 'should be false for priorities other than 1' do
+      for priority in 2..3
+        Task.new(:priority=>priority).high_priority?.should be_false
+      end
+    end
 
-  it 'should be required' do
-    Task.new(default_task.except(:title)).should have(1).error_on(:title)
   end
 
-end
 
+  describe 'due_on' do
 
-describe Task, 'due_on' do
-  include Specs::Tasks
+    it 'should not be required' do
+      Task.create(default_task.except(:due_on)).should have(:no).errors
+    end
 
-  before :each do
-    @task = Task.new(default_task)
-  end
+    it 'should accept time and return date' do
+      now = Time.now
+      Task.create! default_task.merge(:due_on=>now)
+      Task.last.due_on.should == now.to_date
+    end
 
-  it 'should not be required' do
-    Task.create(default_task.except(:due_on)).should have(:no).errors
-  end
+    it 'should accept date and return it' do
+      today = Date.today
+      Task.create! default_task.merge(:due_on=>today)
+      Task.last.due_on.should == today
+    end
 
-  it 'should accept time and return date' do
-    now = Time.now
-    lambda { @task.update_attributes! :due_on=>now ; @task.reload }.should change(@task, :due_on).to(now.to_date)
-  end
+    it 'should accept ISO 8601 date string and return date' do
+      today = Date.today
+      Task.create! default_task.merge(:due_on=>today.to_s)
+      Task.last.due_on.should == today
+    end
 
-  it 'should accept date and return it' do
-    today = Date.today
-    lambda { @task.update_attributes! :due_on=>today ; @task.reload }.should change(@task, :due_on).to(today)
-  end
+    it 'should accept ISO 8601 time string and return date' do
+      now = Time.now
+      Task.create! default_task.merge(:due_on=>now.iso8601)
+      Task.last.due_on.should == now.to_date
+    end
+
+    it 'should accept blank string and set to nil' do
+      Task.create! default_task.merge(:due_on=>Time.now)
+      Task.last.update_attributes :due_on=>''
+      Task.last.due_on.should be_nil
+    end
 
-  it 'should accept ISO 8601 date string and return date' do
-    today = Date.today
-    lambda { @task.update_attributes! :due_on=>today.to_s ; @task.reload }.should change(@task, :due_on).to(today)
   end
 
-  it 'should accept ISO 8601 time string and return date' do
-    now = Time.now
-    lambda { @task.update_attributes! :due_on=>now.iso8601 ; @task.reload }.should change(@task, :due_on).to(now.to_date)
+
+  describe 'over_due?' do
+
+    it 'should be false if task has no due date' do
+      Task.new.over_due?.should be_false
+    end
+
+    it 'should be false if task due date in the future' do
+      Task.new(:due_on=>Date.tomorrow).over_due?.should be_false
+    end
+
+    it 'should be false if task due today' do
+      Task.new(:due_on=>Date.today).over_due?.should be_false
+    end
+
+    it 'should be true if task due date in the past' do
+      Task.new(:due_on=>Date.yesterday).over_due?.should be_true
+    end
+
   end
 
-  it 'should accept blank string and set to nil' do
-    @task.update_attributes! :due_on=>Date.today
-    lambda { @task.update_attributes! :due_on=>'' ; @task.reload }.should change(@task, :due_on).to(nil)
+
+  describe 'ranking'
+
+  describe 'modified_by'
+
+  describe 'activities'
+
+  describe 'with_stakeholders'
+
+  describe 'for_stakeholder'
+
+  describe 'data' do
+
+    it 'should be empty hash by default' do
+      Task.new.data.should == {}
+    end
+
+    it 'should return nothing for new task' do
+      Task.create default_task.except(:data)
+      Task.last.data.should == {}
+    end
+
+    it 'should accept argument for mass assignment' do
+      Task.create default_task
+      lambda { Task.last.update_attributes :data=>{'foo'=>'bar'} }.should change { Task.last.data }.to('foo'=>'bar')
+    end
+
+    it 'should accept nil' do
+      Task.create default_task.merge(:data=>{'foo'=>'bar'})
+      lambda { Task.last.update_attributes :data=>nil }.should change { Task.last.data }.to({})
+    end
+
+    it 'should reject any other value' do
+      Task.create(default_task.merge(:data=>[])).should have(1).error_on(:data)
+      Task.create(default_task.merge(:data=>'string')).should have(1).error_on(:data)
+    end
+
   end
 
 end
 
 
+=begin
+
 describe Task, 'url', :shared=>true do
 
   it 'should be tested for validity' do
@@ -397,39 +475,6 @@
 end
 
 
-describe Task, 'data' do
-  include Specs::Tasks
-
-  before :each do
-  #  @task = Task.create!(default_task)
-  end
-
-  it 'should be empty hash by default' do
-    Task.new.data.should == {}
-  end
-
-  it 'should return nothing for new task' do
-    Task.create default_task.except(:data)
-    Task.first.data.should == {}
-  end
-
-  it 'should accept argument from mass assignment' do
-    Task.create default_task
-    lambda { Task.first.update_attributes :data=>{'foo'=>'bar'} }.should change { Task.first.data }.to('foo'=>'bar')
-  end
-
-  it 'should accept nil' do
-    Task.create default_task.merge(:data=>{'foo'=>'bar'})
-    lambda { Task.first.update_attributes :data=>nil }.should change { Task.first.data }.to({})
-  end
-
-  it 'should reject any other value' do
-    lambda { Task.create default_task.merge(:data=>[]) }.should raise_error(ArgumentError)
-    lambda { Task.create default_task.merge(:data=>'string') }.should raise_error(ArgumentError)
-  end
-
-end
-
 
 describe Task, 'token' do
   include Specs::Tasks