1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
# frozen_string_literal: true
module ActiveRecord
# ActiveRecord::Suppressor prevents the receiver from being saved during
# a given block.
#
# For example, here's a pattern of creating notifications when new comments
# are posted. (The notification may in turn trigger an email, a push
# notification, or just appear in the UI somewhere):
#
# class Comment < ActiveRecord::Base
# belongs_to :commentable, polymorphic: true
# after_create -> { Notification.create! comment: self,
# recipients: commentable.recipients }
# end
#
# That's what you want the bulk of the time. New comment creates a new
# Notification. But there may well be off cases, like copying a commentable
# and its comments, where you don't want that. So you'd have a concern
# something like this:
#
# module Copyable
# def copy_to(destination)
# Notification.suppress do
# # Copy logic that creates new comments that we do not want
# # triggering notifications.
# end
# end
# end
module Suppressor
extend ActiveSupport::Concern
module ClassMethods
def suppress(&block)
previous_state = SuppressorRegistry.suppressed[name]
SuppressorRegistry.suppressed[name] = true
yield
ensure
SuppressorRegistry.suppressed[name] = previous_state
end
end
def save(*, **) # :nodoc:
SuppressorRegistry.suppressed[self.class.name] ? true : super
end
def save!(*, **) # :nodoc:
SuppressorRegistry.suppressed[self.class.name] ? true : super
end
end
class SuppressorRegistry # :nodoc:
extend ActiveSupport::PerThreadRegistry
attr_reader :suppressed
def initialize
@suppressed = {}
end
end
end
|