@@ -82,6 +82,16 @@ def clear
82
82
# # source_location: { filepath: "path/to/file.rb", lineno: 123, label: "UserService#create" }
83
83
# # }
84
84
#
85
+ # ==== Filtered Subscriptions
86
+ #
87
+ # Subscribers can be configured with an optional filter proc to only receive a subset of events:
88
+ #
89
+ # # Only receive events with names starting with "user."
90
+ # Rails.event.subscribe(user_subscriber) { |event| event[:name].start_with?("user.") }
91
+ #
92
+ # # Only receive events with specific payload types
93
+ # Rails.event.subscribe(audit_subscriber) { |event| event[:payload].is_a?(AuditEvent) }
94
+ #
85
95
# The +notify+ API can receive either an event name and a payload hash, or an event object. Names are coerced to strings.
86
96
#
87
97
# ==== Event Objects
@@ -271,12 +281,17 @@ def initialize(*subscribers, raise_on_error: false, tags: nil)
271
281
# timestamp: Float (The timestamp of the event, in nanoseconds)
272
282
# source_location: Hash (The source location of the event, containing the filepath, lineno, and label)
273
283
#
274
- def subscribe ( subscriber )
284
+ # An optional filter proc can be provided to only receive a subset of events:
285
+ #
286
+ # Rails.event.subscribe(subscriber) { |event| event[:name].start_with?("user.") }
287
+ # Rails.event.subscribe(subscriber) { |event| event[:payload].is_a?(UserEvent) }
288
+ #
289
+ def subscribe ( subscriber , &filter )
275
290
unless subscriber . respond_to? ( :emit )
276
291
raise ArgumentError , "Event subscriber #{ subscriber . class . name } must respond to #emit"
277
292
end
278
293
279
- @subscribers << subscriber
294
+ @subscribers << { subscriber : subscriber , filter : filter }
280
295
end
281
296
282
297
# Reports an event to all registered subscribers. An event name and payload can be provided:
@@ -333,7 +348,12 @@ def notify(name_or_object, payload = nil, caller_depth: 1, **kwargs)
333
348
event [ :source_location ] = source_location
334
349
end
335
350
336
- subscribers . each do |subscriber |
351
+ subscribers . each do |subscriber_entry |
352
+ subscriber = subscriber_entry [ :subscriber ]
353
+ filter = subscriber_entry [ :filter ]
354
+
355
+ next if filter && !filter . call ( event )
356
+
337
357
subscriber . emit ( event )
338
358
rescue => subscriber_error
339
359
if raise_on_error
0 commit comments