diff --git a/app/models/inbox.rb b/app/models/inbox.rb index 1a1a0066..96f3dc84 100644 --- a/app/models/inbox.rb +++ b/app/models/inbox.rb @@ -14,15 +14,16 @@ class Inbox < ApplicationRecord end after_create do - user.touch(:inbox_updated_at) + user.touch(:inbox_updated_at) # rubocop:disable Rails/SkipsModelValidations end after_update do - user.touch(:inbox_updated_at) + user.touch(:inbox_updated_at) # rubocop:disable Rails/SkipsModelValidations end after_destroy do - user.touch(:inbox_updated_at) + # user might not exist at this point (account deleted, records are cleaned up async) + user&.touch(:inbox_updated_at) # rubocop:disable Rails/SkipsModelValidations end def answer(answer_content, user) @@ -49,7 +50,7 @@ class Inbox < ApplicationRecord user.profile.anon_display_name || APP_CONFIG["anonymous_name"] else question.user.profile.safe_name - end + end, ), icon: notification_icon, body: question.content.truncate(Question::SHORT_QUESTION_MAX_LENGTH), diff --git a/app/models/notification.rb b/app/models/notification.rb index e36cad0a..76233c67 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -5,15 +5,16 @@ class Notification < ApplicationRecord belongs_to :target, polymorphic: true after_create do - recipient.touch(:notifications_updated_at) + recipient.touch(:notifications_updated_at) # rubocop:disable Rails/SkipsModelValidations end after_update do - recipient.touch(:notifications_updated_at) + recipient.touch(:notifications_updated_at) # rubocop:disable Rails/SkipsModelValidations end after_destroy do - recipient.touch(:notifications_updated_at) + # recipient might not exist at this point (account deleted, records are cleaned up async) + recipient&.touch(:notifications_updated_at) # rubocop:disable Rails/SkipsModelValidations end class << self diff --git a/spec/models/inbox_spec.rb b/spec/models/inbox_spec.rb new file mode 100644 index 00000000..9a00635a --- /dev/null +++ b/spec/models/inbox_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Inbox, type: :model do + describe "associations" do + it { should belong_to(:user) } + it { should belong_to(:question) } + end + + describe "before_destroy" do + let(:user) { FactoryBot.create(:user) } + let(:question) { FactoryBot.create(:question, author_is_anonymous: true) } + + it "does not fail if the user wants to delete their account" do + Inbox.create(user:, question:) + + # this deletes the User record and enqueues the deletion of all + # associated records in sidekiq + user.destroy! + + # so let's drain the queues + expect { Sidekiq::Worker.drain_all }.not_to raise_error + end + end +end diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb new file mode 100644 index 00000000..9bf3aea8 --- /dev/null +++ b/spec/models/notification_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Notification, type: :model do + describe "associations" do + it { should belong_to(:recipient) } + it { should belong_to(:target) } + end + + describe "before_destroy" do + let(:user) { FactoryBot.create(:user) } + let(:answer) { FactoryBot.create(:answer, user: FactoryBot.create(:user)) } + + it "does not fail if the user wants to delete their account" do + Notification::QuestionAnswered.create(recipient: user, target: answer) + + # this deletes the User record and enqueues the deletion of all + # associated records in sidekiq + user.destroy! + + # so let's drain the queues + expect { Sidekiq::Worker.drain_all }.not_to raise_error + end + end +end