Skip to content

Commit 6a2a397

Browse files
committed
Allow unsubscribing from events
1 parent a266aef commit 6a2a397

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

activesupport/lib/active_support/event_reporter.rb

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ def clear
214214
# end
215215
#
216216
class EventReporter
217-
attr_reader :subscribers
218-
attr_accessor :raise_on_error
217+
attr_reader :subscribers # :nodoc:
218+
attr_reader :raise_on_error # :nodoc:
219219

220220
class << self
221221
attr_accessor :context_store # :nodoc:
@@ -254,6 +254,12 @@ def initialize(*subscribers, raise_on_error: false, tags: nil)
254254
@raise_on_error = raise_on_error
255255
end
256256

257+
# Sets whether to raise an error if a subscriber raises an error during
258+
# event emission, or when unexpected arguments are passed to +notify+.
259+
def raise_on_error=(value)
260+
@raise_on_error = value
261+
end
262+
257263
# Registers a new event subscriber. The subscriber must respond to
258264
#
259265
# emit(event: Hash)
@@ -270,10 +276,21 @@ def subscribe(subscriber)
270276
unless subscriber.respond_to?(:emit)
271277
raise ArgumentError, "Event subscriber #{subscriber.class.name} must respond to #emit"
272278
end
273-
274279
@subscribers << subscriber
275280
end
276281

282+
# Unregister an event subscriber. Accepts either a subscriber or a class.
283+
#
284+
# subscriber = MyEventSubscriber.new
285+
# Rails.event.subscribe(subscriber)
286+
#
287+
# Rails.event.unsubscribe(subscriber)
288+
# # or
289+
# Rails.event.unsubscribe(MyEventSubscriber)
290+
def unsubscribe(subscriber)
291+
@subscribers.delete_if { |s| subscriber === s }
292+
end
293+
277294
# Reports an event to all registered subscribers. An event name and payload can be provided:
278295
#
279296
# Rails.event.notify("user.created", { id: 123 })

activesupport/test/event_reporter_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,25 @@ def initialize(http_method, http_status)
5555
assert_equal "Event subscriber Object must respond to #emit", error.message
5656
end
5757

58+
test "#unsubscribe" do
59+
second_subscriber = EventSubscriber.new
60+
@reporter.subscribe(second_subscriber)
61+
@reporter.notify(:test_event, key: "value")
62+
63+
assert event_matcher(name: "test_event", payload: { key: "value" }).call(second_subscriber.events.last)
64+
65+
@reporter.unsubscribe(second_subscriber)
66+
67+
assert_not_called(second_subscriber, :emit, [
68+
event_matcher(name: "another_event")
69+
]) do
70+
@reporter.notify(:another_event, key: "value")
71+
end
72+
73+
@reporter.notify(:last_event, key: "value")
74+
assert_empty second_subscriber.events.select(&event_matcher(name: "last_event", payload: { key: "value" }))
75+
end
76+
5877
test "#notify with name" do
5978
assert_called_with(@subscriber, :emit, [
6079
event_matcher(name: "test_event")

0 commit comments

Comments
 (0)