diff --git a/app/jobs/notifications/remove_all_job.rb b/app/jobs/notifications/remove_all_job.rb new file mode 100644 index 000000000..d312cfb14 --- /dev/null +++ b/app/jobs/notifications/remove_all_job.rb @@ -0,0 +1,9 @@ +module Notifications + class RemoveAllJob < ApplicationJob + queue_as :remove_all_notifications + + def perform(notifiable_id, notifiable_type, action, service = Notifications::RemoveAll) + service.call(notifiable_id, notifiable_type, action) + end + end +end diff --git a/app/models/notification.rb b/app/models/notification.rb index c72a44510..ea4801edf 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -137,14 +137,13 @@ class Notification < ApplicationRecord Notifications::MilestoneJob.perform_now(type, article_id) end - def remove_all(notifiable_hash) - Notification.where( - notifiable_id: notifiable_hash[:notifiable_id], - notifiable_type: notifiable_hash[:notifiable_type], - action: notifiable_hash[:action], - ).delete_all + def remove_all(notifiable_id:, notifiable_type:, action: nil) + Notifications::RemoveAllJob.perform_later(notifiable_id, notifiable_type, action) + end + + def remove_all_without_delay(notifiable_id:, notifiable_type:, action: nil) + Notifications::RemoveAllJob.perform_now(notifiable_id, notifiable_type, action) end - handle_asynchronously :remove_all def remove_each(notifiable_collection, action = nil) # only used for mentions since it's an array diff --git a/app/services/notifications/remove_all.rb b/app/services/notifications/remove_all.rb new file mode 100644 index 000000000..fe630707b --- /dev/null +++ b/app/services/notifications/remove_all.rb @@ -0,0 +1,25 @@ +module Notifications + class RemoveAll + def initialize(notifiable_id, notifiable_type, action) + @notifiable_id = notifiable_id + @notifiable_type = notifiable_type + @action = action + end + + def self.call(*args) + new(*args).call + end + + def call + Notification.where( + notifiable_id: notifiable_id, + notifiable_type: notifiable_type, + action: action, + ).delete_all + end + + private + + attr_reader :notifiable_id, :notifiable_type, :action + end +end diff --git a/spec/jobs/notifications/remove_all_job_spec.rb b/spec/jobs/notifications/remove_all_job_spec.rb new file mode 100644 index 000000000..80f78f302 --- /dev/null +++ b/spec/jobs/notifications/remove_all_job_spec.rb @@ -0,0 +1,18 @@ +require "rails_helper" + +RSpec.describe Notifications::RemoveAllJob, type: :job do + include_examples "#enqueues_job", "remove_all_notifications", {} + + describe "#perform_now" do + let(:remove_all_service) { double } + + before do + allow(remove_all_service).to receive(:call) + end + + it "calls the service" do + described_class.perform_now(666, "Article", "Published", remove_all_service) + expect(remove_all_service).to have_received(:call).with(666, "Article", "Published") + end + end +end diff --git a/spec/services/notifications/remove_all_spec.rb b/spec/services/notifications/remove_all_spec.rb new file mode 100644 index 000000000..03cb140eb --- /dev/null +++ b/spec/services/notifications/remove_all_spec.rb @@ -0,0 +1,20 @@ +require "rails_helper" + +RSpec.describe Notifications::RemoveAll do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:organization) { create(:organization) } + let(:article) { create(:article) } + let(:article2) { create(:article) } + let(:comment) { create(:comment, user_id: user.id, commentable_id: article.id, commentable_type: "Article") } + + before do + create(:notification, user: user, organization: organization, notifiable_id: article.id, notifiable_type: "Article", action: "Published") + create(:notification, user: user2, organization: organization, notifiable_id: article.id, notifiable_type: "Article", action: "Published") + create(:notification, user: user, organization: organization, notifiable_id: comment.id, notifiable_type: "Comment", action: "Reaction") + end + + it "checks all notifications for an article are deleted and only for an article" do + expect { described_class.call(article.id, "Article", "Published") }.to change(Notification, :count).by(-2) + end +end