From 9ae9aed01068d90bf337f91e871f9dfe56b8a969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 19 Aug 2015 22:40:20 +0200 Subject: [PATCH] FIX: change **default** notification state when a topic is recategorized within 5 days of creation --- app/models/category_user.rb | 47 +++++++++++++++++++++---------- app/models/topic.rb | 4 +-- spec/models/category_user_spec.rb | 17 ++++++++++- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/app/models/category_user.rb b/app/models/category_user.rb index d53fb804e29..1fb537f546e 100644 --- a/app/models/category_user.rb +++ b/app/models/category_user.rb @@ -15,18 +15,19 @@ class CategoryUser < ActiveRecord::Base TopicUser.notification_levels end - def self.auto_track_new_topic(topic) - apply_default_to_topic(topic, - TopicUser.notification_levels[:tracking], - TopicUser.notification_reasons[:auto_track_category] - ) - end + %w{watch track}.each do |s| + define_singleton_method("auto_#{s}_new_topic") do |topic, new_category=nil| + category_id = topic.category_id - def self.auto_watch_new_topic(topic) - apply_default_to_topic(topic, - TopicUser.notification_levels[:watching], - TopicUser.notification_reasons[:auto_watch_category] - ) + if new_category && topic.created_at > 5.days.ago + # we want to apply default of the new category + category_id = new_category.id + # remove defaults from previous category + remove_default_from_topic(topic.id, TopicUser.notification_levels[:"#{s}ing"], TopicUser.notification_reasons[:"auto_#{s}_category"]) + end + + apply_default_to_topic(topic.id, category_id, TopicUser.notification_levels[:"#{s}ing"], TopicUser.notification_reasons[:"auto_#{s}_category"]) + end end def self.batch_set(user, level, category_ids) @@ -56,7 +57,7 @@ class CategoryUser < ActiveRecord::Base end end - def self.apply_default_to_topic(topic, level, reason) + def self.apply_default_to_topic(topic_id, category_id, level, reason) # Can not afford to slow down creation of topics when a pile of users are watching new topics, reverting to SQL for max perf here sql = <<-SQL INSERT INTO topic_users(user_id, topic_id, notification_level, notifications_reason_id) @@ -68,14 +69,30 @@ class CategoryUser < ActiveRecord::Base SQL exec_sql(sql, - topic_id: topic.id, - category_id: topic.category_id, + topic_id: topic_id, + category_id: category_id, level: level, reason: reason ) end - private_class_method :apply_default_to_topic + def self.remove_default_from_topic(topic_id, level, reason) + sql = <<-SQL + DELETE FROM topic_users + WHERE topic_id = :topic_id + AND notifications_changed_at IS NULL + AND notification_level = :level + AND notifications_reason_id = :reason + SQL + + exec_sql(sql, + topic_id: topic_id, + level: level, + reason: reason + ) + end + + private_class_method :apply_default_to_topic, :remove_default_from_topic end # == Schema Information diff --git a/app/models/topic.rb b/app/models/topic.rb index 30bd8fc343a..297f840be3c 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -482,8 +482,8 @@ class Topic < ActiveRecord::Base Category.where(id: new_category.id).update_all("topic_count = topic_count + 1") CategoryFeaturedTopic.feature_topics_for(old_category) unless @import_mode CategoryFeaturedTopic.feature_topics_for(new_category) unless @import_mode || old_category.id == new_category.id - CategoryUser.auto_watch_new_topic(self) - CategoryUser.auto_track_new_topic(self) + CategoryUser.auto_watch_new_topic(self, new_category) + CategoryUser.auto_track_new_topic(self, new_category) end true diff --git a/spec/models/category_user_spec.rb b/spec/models/category_user_spec.rb index 749368e64e7..34927139996 100644 --- a/spec/models/category_user_spec.rb +++ b/spec/models/category_user_spec.rb @@ -52,8 +52,8 @@ describe CategoryUser do end it "watches categories that have been changed" do - watched_category = Fabricate(:category) user = Fabricate(:user) + watched_category = Fabricate(:category) CategoryUser.create!(user: user, category: watched_category, notification_level: CategoryUser.notification_levels[:watching]) post = create_post @@ -65,6 +65,21 @@ describe CategoryUser do expect(tu.notification_level).to eq TopicUser.notification_levels[:watching] end + it "unwatches categories that have been changed" do + user = Fabricate(:user) + watched_category = Fabricate(:category) + CategoryUser.create!(user: user, category: watched_category, notification_level: CategoryUser.notification_levels[:watching]) + + post = create_post(category: watched_category) + tu = TopicUser.get(post.topic, user) + expect(tu.notification_level).to eq TopicUser.notification_levels[:watching] + + # Now, change the topic's category + unwatched_category = Fabricate(:category) + post.topic.change_category_to_id(unwatched_category.id) + expect(TopicUser.get(post.topic, user)).to be_blank + end + end end