diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index 554279d21..79b4b616a 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -24,7 +24,7 @@ class MessagesController < ApplicationController
verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show }
verify :xhr => true, :only => :quote
-
+ helper :watchers
helper :attachments
include AttachmentsHelper
diff --git a/app/models/message.rb b/app/models/message.rb
index 80df7a33a..f1cb2d0ba 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -33,11 +33,14 @@ class Message < ActiveRecord::Base
{:id => o.parent_id, :anchor => "message-#{o.id}"})}
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]}
+ acts_as_watchable
attr_protected :locked, :sticky
validates_presence_of :subject, :content
validates_length_of :subject, :maximum => 255
+ after_create :add_author_as_watcher
+
def validate_on_create
# Can not reply to a locked topic
errors.add_to_base 'Topic is locked' if root.locked? && self != root
@@ -68,4 +71,10 @@ class Message < ActiveRecord::Base
def project
board.project
end
+
+ private
+
+ def add_author_as_watcher
+ Watcher.create(:watchable => self.root, :user => author)
+ end
end
diff --git a/app/models/message_observer.rb b/app/models/message_observer.rb
index 043988172..d37b53813 100644
--- a/app/models/message_observer.rb
+++ b/app/models/message_observer.rb
@@ -17,8 +17,9 @@
class MessageObserver < ActiveRecord::Observer
def after_create(message)
- # send notification to the authors of the thread
- recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author && m.author.active?}
+ recipients = []
+ # send notification to the topic watchers
+ recipients += message.root.watcher_recipients
# send notification to the board watchers
recipients += message.board.watcher_recipients
# send notification to project members who want to be notified
diff --git a/app/views/messages/show.rhtml b/app/views/messages/show.rhtml
index c24be7a21..31696d56d 100644
--- a/app/views/messages/show.rhtml
+++ b/app/views/messages/show.rhtml
@@ -2,6 +2,7 @@
link_to(h(@board.name), {:controller => 'boards', :action => 'show', :project_id => @project, :id => @board}) %>
+ <%= watcher_tag(@topic, User.current) %>
<%= link_to_remote_if_authorized l(:button_quote), { :url => {:action => 'quote', :id => @topic} }, :class => 'icon icon-comment' %>
<%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => @topic}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => @topic}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %>
diff --git a/db/migrate/098_set_topic_authors_as_watchers.rb b/db/migrate/098_set_topic_authors_as_watchers.rb
new file mode 100644
index 000000000..5bc41fb38
--- /dev/null
+++ b/db/migrate/098_set_topic_authors_as_watchers.rb
@@ -0,0 +1,14 @@
+class SetTopicAuthorsAsWatchers < ActiveRecord::Migration
+ def self.up
+ # Sets active users who created/replied a topic as watchers of the topic
+ # so that the new watch functionality at topic level doesn't affect notifications behaviour
+ Message.connection.execute("INSERT INTO watchers (watchable_type, watchable_id, user_id)" +
+ " SELECT DISTINCT 'Message', COALESCE(messages.parent_id, messages.id), messages.author_id FROM messages, users" +
+ " WHERE messages.author_id = users.id AND users.status = 1")
+ end
+
+ def self.down
+ # Removes all message watchers
+ Watcher.delete_all("watchable_type = 'Message'")
+ end
+end
diff --git a/test/fixtures/watchers.yml b/test/fixtures/watchers.yml
index a8c482955..6c8cdfb5e 100644
--- a/test/fixtures/watchers.yml
+++ b/test/fixtures/watchers.yml
@@ -3,4 +3,8 @@ watchers_001:
watchable_type: Issue
watchable_id: 2
user_id: 3
+watchers_002:
+ watchable_type: Message
+ watchable_id: 1
+ user_id: 1
\ No newline at end of file
diff --git a/test/unit/message_test.rb b/test/unit/message_test.rb
index 82ed3fe13..6e8e8fb26 100644
--- a/test/unit/message_test.rb
+++ b/test/unit/message_test.rb
@@ -1,7 +1,7 @@
require File.dirname(__FILE__) + '/../test_helper'
class MessageTest < Test::Unit::TestCase
- fixtures :projects, :boards, :messages
+ fixtures :projects, :boards, :messages, :users, :watchers
def setup
@board = Board.find(1)
@@ -20,6 +20,8 @@ class MessageTest < Test::Unit::TestCase
# messages count incremented
assert_equal messages_count+1, @board[:messages_count]
assert_equal message, @board.last_message
+ # author should be watching the message
+ assert message.watched_by?(@user)
end
def test_reply
@@ -28,7 +30,8 @@ class MessageTest < Test::Unit::TestCase
@message = Message.find(1)
replies_count = @message.replies_count
- reply = Message.new(:board => @board, :subject => 'Test reply', :content => 'Test reply content', :parent => @message, :author => @user)
+ reply_author = User.find(2)
+ reply = Message.new(:board => @board, :subject => 'Test reply', :content => 'Test reply content', :parent => @message, :author => reply_author)
assert reply.save
@board.reload
# same topics count
@@ -40,13 +43,18 @@ class MessageTest < Test::Unit::TestCase
# replies count incremented
assert_equal replies_count+1, @message[:replies_count]
assert_equal reply, @message.last_reply
+ # author should be watching the message
+ assert @message.watched_by?(reply_author)
end
def test_destroy_topic
message = Message.find(1)
board = message.board
topics_count, messages_count = board.topics_count, board.messages_count
- assert message.destroy
+
+ assert_difference('Watcher.count', -1) do
+ assert message.destroy
+ end
board.reload
# Replies deleted
@@ -54,6 +62,7 @@ class MessageTest < Test::Unit::TestCase
# Checks counters
assert_equal topics_count - 1, board.topics_count
assert_equal messages_count - 3, board.messages_count
+ # Watchers removed
end
def test_destroy_reply