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