Commit b6eabacb30256369e13b122362ac584a3a45ab21
1 parent
83f48698
Exists in
master
and in
29 other branches
ActionItem96: implementing task system
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@611 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
3 changed files
with
134 additions
and
2 deletions
Show diff stats
app/models/task.rb
1 | +# Task is the base class of ... tasks! Its instances represents tasks that must | |
2 | +# be confirmed by someone (like an environment administrator) or by noosfero | |
3 | +# itself. | |
4 | +# | |
5 | +# The specific types of tasks <em>must</em> override the #perform method, so | |
6 | +# the actual action associated to the type of task can be performed. See the | |
7 | +# documentation of the #perform method for details. | |
8 | +# | |
9 | +# This class has a +status+ field of type <tt>text</tt>, where you can store | |
10 | +# any type of data (as serialized Ruby objects) you need for your subclass . | |
1 | 11 | class Task < ActiveRecord::Base |
12 | + | |
13 | + module Status | |
14 | + # the status of tasks just created | |
15 | + ACTIVE = 1 | |
16 | + | |
17 | + # the status of a task that was cancelled. | |
18 | + CANCELLED = 2 | |
19 | + | |
20 | + # the status os a task that was successfully finished | |
21 | + FINISHED = 3 | |
22 | + end | |
23 | + | |
2 | 24 | belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
3 | 25 | belongs_to :target, :class_name => 'Profile', :foreign_key => :target_id |
26 | + | |
27 | + def initialize(*args) | |
28 | + super | |
29 | + self.status ||= Task::Status::ACTIVE | |
30 | + end | |
31 | + | |
32 | + # this method finished the task. It calls #perform, which must be overriden | |
33 | + # by subclasses. At the end a message (as returned by #finish_message) is | |
34 | + # sent to the requestor with #notify_requestor. | |
35 | + def finish | |
36 | + transaction do | |
37 | + self.status = Task::Status::FINISHED | |
38 | + self.end_date = Time.now | |
39 | + self.save! | |
40 | + self.perform | |
41 | + self.notify_requestor(self.finish_message) | |
42 | + end | |
43 | + end | |
44 | + | |
45 | + # this method cancels the task. At the end a message (as returned by | |
46 | + # #cancel_message) is sent to the requestor with #notify_requestor. | |
47 | + def cancel | |
48 | + transaction do | |
49 | + self.status = Task::Status::CANCELLED | |
50 | + self.end_date = Time.now | |
51 | + self.save! | |
52 | + self.notify_requestor(self.cancel_message) | |
53 | + end | |
54 | + end | |
55 | + | |
56 | + protected | |
57 | + | |
58 | + # This method must be overrided in subclasses, and its implementation must do | |
59 | + # the job the task is intended to. This method will be called when the finish | |
60 | + # method is called. | |
61 | + # | |
62 | + # To cancel the finish of the task, you can throw an exception in perform. | |
63 | + # | |
64 | + # The implementation on Task class just does nothing. | |
65 | + def perform | |
66 | + end | |
67 | + | |
68 | + # sends a message to the requestor | |
69 | + def notify_requestor(msg) | |
70 | + # TODO: implement message sending | |
71 | + end | |
72 | + | |
73 | + # The message that will be sent to the requestor of the task when its | |
74 | + # finished. | |
75 | + def finish_message | |
76 | + _("The task was finished at %s") % (self.end_date.to_s) | |
77 | + end | |
78 | + | |
79 | + # The message that will be sent to the requestor of the task when its | |
80 | + # cancelled. | |
81 | + def cancel_message | |
82 | + _("The task was cancelled at %s") % (self.end_date.to_s) | |
83 | + end | |
84 | + | |
4 | 85 | end | ... | ... |
db/migrate/017_create_tasks.rb
1 | 1 | class CreateTasks < ActiveRecord::Migration |
2 | 2 | def self.up |
3 | 3 | create_table :tasks do |t| |
4 | + t.column :description, :string | |
4 | 5 | |
5 | 6 | t.column :data, :text |
6 | 7 | t.column :status, :integer |
8 | + t.column :end_date, :date | |
7 | 9 | |
8 | 10 | t.column :requestor_id, :integer |
9 | 11 | t.column :target_id, :integer | ... | ... |
test/unit/task_test.rb
... | ... | @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper' |
3 | 3 | class TaskTest < Test::Unit::TestCase |
4 | 4 | |
5 | 5 | def test_relationship_with_requestor |
6 | - t = Task.new | |
6 | + t = Task.create | |
7 | 7 | assert_raise ActiveRecord::AssociationTypeMismatch do |
8 | 8 | t.requestor = 1 |
9 | 9 | end |
... | ... | @@ -13,7 +13,7 @@ class TaskTest < Test::Unit::TestCase |
13 | 13 | end |
14 | 14 | |
15 | 15 | def test_relationship_with_target |
16 | - t = Task.new | |
16 | + t = Task.create | |
17 | 17 | assert_raise ActiveRecord::AssociationTypeMismatch do |
18 | 18 | t.target = 1 |
19 | 19 | end |
... | ... | @@ -21,4 +21,53 @@ class TaskTest < Test::Unit::TestCase |
21 | 21 | t.target = Profile.new |
22 | 22 | end |
23 | 23 | end |
24 | + | |
25 | + def test_should_call_perform_in_finish | |
26 | + t = Task.create | |
27 | + t.expects(:perform) | |
28 | + t.finish | |
29 | + assert_equal Task::Status::FINISHED, t.status | |
30 | + end | |
31 | + | |
32 | + def test_should_have_cancelled_status_after_cancel | |
33 | + t = Task.create | |
34 | + t.cancel | |
35 | + assert_equal Task::Status::CANCELLED, t.status | |
36 | + end | |
37 | + | |
38 | + def test_should_start_with_active_status | |
39 | + t = Task.create | |
40 | + assert_equal Task::Status::ACTIVE, t.status | |
41 | + end | |
42 | + | |
43 | + def test_should_notify_finish | |
44 | + t = Task.create | |
45 | + t.expects(:notify_requestor) | |
46 | + t.expects(:finish_message) | |
47 | + t.finish | |
48 | + end | |
49 | + | |
50 | + def test_should_notify_cancel | |
51 | + t = Task.create | |
52 | + t.expects(:notify_requestor) | |
53 | + t.expects(:cancel_message) | |
54 | + t.cancel | |
55 | + end | |
56 | + | |
57 | + def test_should_not_notify_when_perform_fails | |
58 | + count = Task.count | |
59 | + | |
60 | + t = Task.create | |
61 | + class << t | |
62 | + def perform | |
63 | + raise RuntimeError | |
64 | + end | |
65 | + end | |
66 | + | |
67 | + t.expects(:notify_requestor).never | |
68 | + assert_raise RuntimeError do | |
69 | + t.finish | |
70 | + end | |
71 | + end | |
72 | + | |
24 | 73 | end | ... | ... |