Skip to content

Commit a5be7da

Browse files
committed
Allow unsubscribing from events
1 parent 2ca2634 commit a5be7da

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
@@ -231,8 +231,8 @@ def clear
231231
# # payload: { id: 123 },
232232
# # }
233233
class EventReporter
234-
attr_reader :subscribers
235-
attr_accessor :raise_on_error
234+
attr_reader :subscribers # :nodoc:
235+
attr_reader :raise_on_error # :nodoc:
236236

237237
ENCODERS = {
238238
json: Encoders::JSON,
@@ -272,6 +272,12 @@ def initialize(*subscribers, raise_on_error: false, tags: nil)
272272
@raise_on_error = raise_on_error
273273
end
274274

275+
# Sets whether to raise an error if a subscriber raises an error during
276+
# event emission, or when unexpected arguments are passed to +notify+.
277+
def raise_on_error=(value)
278+
@raise_on_error = value
279+
end
280+
275281
# Registers a new event subscriber. The subscriber must respond to
276282
#
277283
# emit(event: Hash)
@@ -293,10 +299,21 @@ def subscribe(subscriber, &filter)
293299
unless subscriber.respond_to?(:emit)
294300
raise ArgumentError, "Event subscriber #{subscriber.class.name} must respond to #emit"
295301
end
296-
297302
@subscribers << { subscriber: subscriber, filter: filter }
298303
end
299304

305+
# Unregister an event subscriber. Accepts either a subscriber or a class.
306+
#
307+
# subscriber = MyEventSubscriber.new
308+
# Rails.event.subscribe(subscriber)
309+
#
310+
# Rails.event.unsubscribe(subscriber)
311+
# # or
312+
# Rails.event.unsubscribe(MyEventSubscriber)
313+
def unsubscribe(subscriber)
314+
@subscribers.delete_if { |s| subscriber === s }
315+
end
316+
300317
# Reports an event to all registered subscribers. An event name and payload can be provided:
301318
#
302319
# 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
@@ -72,6 +72,25 @@ def emit(event)
7272
assert_equal "Event subscriber Object must respond to #emit", error.message
7373
end
7474

75+
test "#unsubscribe" do
76+
second_subscriber = EventSubscriber.new
77+
@reporter.subscribe(second_subscriber)
78+
@reporter.notify(:test_event, key: "value")
79+
80+
assert event_matcher(name: "test_event", payload: { key: "value" }).call(second_subscriber.events.last)
81+
82+
@reporter.unsubscribe(second_subscriber)
83+
84+
assert_not_called(second_subscriber, :emit, [
85+
event_matcher(name: "another_event")
86+
]) do
87+
@reporter.notify(:another_event, key: "value")
88+
end
89+
90+
@reporter.notify(:last_event, key: "value")
91+
assert_empty second_subscriber.events.select(&event_matcher(name: "last_event", payload: { key: "value" }))
92+
end
93+
7594
test "#notify with name" do
7695
assert_called_with(@subscriber, :emit, [
7796
event_matcher(name: "test_event")

0 commit comments

Comments
 (0)