diff --git a/app/models/category.rb b/app/models/category.rb index e19556c2697..455e50cbe8b 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -188,11 +188,16 @@ class Category < ActiveRecord::Base DB.exec <<~SQL UPDATE categories c - SET topic_count = x.topic_count, - post_count = x.post_count - FROM (#{topics_with_post_count}) x + SET topic_count = COALESCE(x.topic_count, 0), + post_count = COALESCE(x.post_count, 0) + FROM ( + SELECT ccc.id as category_id, stats.topic_count, stats.post_count + FROM categories ccc + LEFT JOIN (#{topics_with_post_count}) stats + ON stats.category_id = ccc.id + ) x WHERE x.category_id = c.id - AND (c.topic_count <> x.topic_count OR c.post_count <> x.post_count) + AND (c.topic_count <> COALESCE(x.topic_count, 0) OR c.post_count <> COALESCE(x.post_count, 0)) SQL # Yes, there are a lot of queries happening below. diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index f268c2c7356..fa9cf430104 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -642,6 +642,22 @@ describe Category do expect(@uncategorized.posts_week).to eq(1) end end + + context 'when there are no topics left' do + let!(:topic) { create_post(user: @category.user, category: @category.id).reload.topic } + + it 'can update the topic count to zero' do + @category.reload + expect(@category.topic_count).to eq(1) + expect(@category.topics.count).to eq(2) + topic.delete # Delete so the post trash/destroy hook doesn't fire + + Category.update_stats + @category.reload + expect(@category.topics.count).to eq(1) + expect(@category.topic_count).to eq(0) + end + end end describe "#url" do