From b6eabacb30256369e13b122362ac584a3a45ab21 Mon Sep 17 00:00:00 2001 From: AntonioTerceiro Date: Wed, 3 Oct 2007 20:05:09 +0000 Subject: [PATCH] ActionItem96: implementing task system --- app/models/task.rb | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ db/migrate/017_create_tasks.rb | 2 ++ test/unit/task_test.rb | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/app/models/task.rb b/app/models/task.rb index c64096d..1f64f1a 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -1,4 +1,85 @@ +# Task is the base class of ... tasks! Its instances represents tasks that must +# be confirmed by someone (like an environment administrator) or by noosfero +# itself. +# +# The specific types of tasks must override the #perform method, so +# the actual action associated to the type of task can be performed. See the +# documentation of the #perform method for details. +# +# This class has a +status+ field of type text, where you can store +# any type of data (as serialized Ruby objects) you need for your subclass . class Task < ActiveRecord::Base + + module Status + # the status of tasks just created + ACTIVE = 1 + + # the status of a task that was cancelled. + CANCELLED = 2 + + # the status os a task that was successfully finished + FINISHED = 3 + end + belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id belongs_to :target, :class_name => 'Profile', :foreign_key => :target_id + + def initialize(*args) + super + self.status ||= Task::Status::ACTIVE + end + + # this method finished the task. It calls #perform, which must be overriden + # by subclasses. At the end a message (as returned by #finish_message) is + # sent to the requestor with #notify_requestor. + def finish + transaction do + self.status = Task::Status::FINISHED + self.end_date = Time.now + self.save! + self.perform + self.notify_requestor(self.finish_message) + end + end + + # this method cancels the task. At the end a message (as returned by + # #cancel_message) is sent to the requestor with #notify_requestor. + def cancel + transaction do + self.status = Task::Status::CANCELLED + self.end_date = Time.now + self.save! + self.notify_requestor(self.cancel_message) + end + end + + protected + + # This method must be overrided in subclasses, and its implementation must do + # the job the task is intended to. This method will be called when the finish + # method is called. + # + # To cancel the finish of the task, you can throw an exception in perform. + # + # The implementation on Task class just does nothing. + def perform + end + + # sends a message to the requestor + def notify_requestor(msg) + # TODO: implement message sending + end + + # The message that will be sent to the requestor of the task when its + # finished. + def finish_message + _("The task was finished at %s") % (self.end_date.to_s) + end + + # The message that will be sent to the requestor of the task when its + # cancelled. + def cancel_message + _("The task was cancelled at %s") % (self.end_date.to_s) + end + end diff --git a/db/migrate/017_create_tasks.rb b/db/migrate/017_create_tasks.rb index 6ca2f4a..5c045ae 100644 --- a/db/migrate/017_create_tasks.rb +++ b/db/migrate/017_create_tasks.rb @@ -1,9 +1,11 @@ class CreateTasks < ActiveRecord::Migration def self.up create_table :tasks do |t| + t.column :description, :string t.column :data, :text t.column :status, :integer + t.column :end_date, :date t.column :requestor_id, :integer t.column :target_id, :integer diff --git a/test/unit/task_test.rb b/test/unit/task_test.rb index ef07fb6..40e3b63 100644 --- a/test/unit/task_test.rb +++ b/test/unit/task_test.rb @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper' class TaskTest < Test::Unit::TestCase def test_relationship_with_requestor - t = Task.new + t = Task.create assert_raise ActiveRecord::AssociationTypeMismatch do t.requestor = 1 end @@ -13,7 +13,7 @@ class TaskTest < Test::Unit::TestCase end def test_relationship_with_target - t = Task.new + t = Task.create assert_raise ActiveRecord::AssociationTypeMismatch do t.target = 1 end @@ -21,4 +21,53 @@ class TaskTest < Test::Unit::TestCase t.target = Profile.new end end + + def test_should_call_perform_in_finish + t = Task.create + t.expects(:perform) + t.finish + assert_equal Task::Status::FINISHED, t.status + end + + def test_should_have_cancelled_status_after_cancel + t = Task.create + t.cancel + assert_equal Task::Status::CANCELLED, t.status + end + + def test_should_start_with_active_status + t = Task.create + assert_equal Task::Status::ACTIVE, t.status + end + + def test_should_notify_finish + t = Task.create + t.expects(:notify_requestor) + t.expects(:finish_message) + t.finish + end + + def test_should_notify_cancel + t = Task.create + t.expects(:notify_requestor) + t.expects(:cancel_message) + t.cancel + end + + def test_should_not_notify_when_perform_fails + count = Task.count + + t = Task.create + class << t + def perform + raise RuntimeError + end + end + + t.expects(:notify_requestor).never + assert_raise RuntimeError do + t.finish + end + end + end -- libgit2 0.21.2