From d010816ba876bf4f749749e9d7432a843e8a1ff9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 18 Aug 2018 03:03:23 +0200 Subject: [PATCH] Fix error when trying to update counters for statuses that are gone (#8251) --- app/models/favourite.rb | 4 ++-- app/models/status.rb | 10 ++++++---- spec/models/status_spec.rb | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/models/favourite.rb b/app/models/favourite.rb index ce7a6a336..17f8c9fa6 100644 --- a/app/models/favourite.rb +++ b/app/models/favourite.rb @@ -32,11 +32,11 @@ class Favourite < ApplicationRecord private def increment_cache_counters - status.increment_count!(:favourites_count) + status&.increment_count!(:favourites_count) end def decrement_cache_counters return if association(:status).loaded? && (status.marked_for_destruction? || status.marked_for_mass_destruction?) - status.decrement_count!(:favourites_count) + status&.decrement_count!(:favourites_count) end end diff --git a/app/models/status.rb b/app/models/status.rb index 2eed33659..533d12354 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -396,6 +396,8 @@ class Status < ApplicationRecord private def update_status_stat!(attrs) + return if marked_for_destruction? || destroyed? + record = status_stat || build_status_stat record.update(attrs) end @@ -456,8 +458,8 @@ class Status < ApplicationRecord Account.where(id: account_id).update_all('statuses_count = COALESCE(statuses_count, 0) + 1') end - reblog.increment_count!(:reblogs_count) if reblog? - thread.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) + reblog&.increment_count!(:reblogs_count) if reblog? + thread&.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) end def decrement_counter_caches @@ -469,7 +471,7 @@ class Status < ApplicationRecord Account.where(id: account_id).update_all('statuses_count = GREATEST(COALESCE(statuses_count, 0) - 1, 0)') end - reblog.decrement_count!(:reblogs_count) if reblog? - thread.decrement_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) + reblog&.decrement_count!(:reblogs_count) if reblog? + thread&.decrement_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index b3e475d99..d03005107 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -182,6 +182,27 @@ RSpec.describe Status, type: :model do reblog.destroy expect(subject.reblogs_count).to eq 0 end + + it 'does not fail when original is deleted before reblog' do + reblog = Fabricate(:status, account: bob, reblog: subject) + expect(subject.reblogs_count).to eq 1 + expect { subject.destroy }.to_not raise_error + expect(Status.find_by(id: reblog.id)).to be_nil + end + end + + describe '#replies_count' do + it 'is the number of replies' do + reply = Fabricate(:status, account: bob, thread: subject) + expect(subject.replies_count).to eq 1 + end + + it 'is decremented when reply is removed' do + reply = Fabricate(:status, account: bob, thread: subject) + expect(subject.replies_count).to eq 1 + reply.destroy + expect(subject.replies_count).to eq 0 + end end describe '#favourites_count' do