Module: Spree::Events
- Defined in:
- lib/spree/events.rb,
lib/spree/events/registry.rb,
lib/spree/events/adapters/base.rb,
app/jobs/spree/events/subscriber_job.rb,
lib/spree/events/adapters/active_support_notifications.rb
Overview
Main entry point for the Spree event system.
This module provides a clean API for publishing events and subscribing to them. It abstracts the underlying implementation (ActiveSupport::Notifications) allowing for future changes without affecting subscriber code.
Defined Under Namespace
Modules: Adapters Classes: Registry, SubscriberJob
Class Attribute Summary collapse
-
.log_subscription ⇒ Object
Reference to the AS::N subscription created by Spree::EventLogSubscriber.
Class Method Summary collapse
-
.activate! ⇒ Object
Activate the event system (called during Rails initialization) Also registers all subscribers from Spree.subscribers This method is idempotent - calling it multiple times has no effect.
-
.adapter ⇒ Object
Get the adapter instance.
-
.disable { ... } ⇒ Object
Temporarily disable events within a block.
-
.disable! ⇒ void
Globally disable events.
-
.enable { ... } ⇒ Object
Temporarily enable events within a block Useful for testing when events are globally disabled.
-
.enable! ⇒ void
Globally enable events Useful for testing.
-
.enabled? ⇒ Boolean
Check if events are enabled.
-
.patterns ⇒ Array<String>
List all registered subscriber patterns.
-
.publish(name, payload = {}, metadata = {}) ⇒ Spree::Event
Publish an event to all matching subscribers.
-
.register_subscribers! ⇒ void
Register all subscribers from Spree.subscribers.
-
.registry ⇒ Spree::Events::Registry
Get the event registry.
-
.reset! ⇒ Object
Reset the event system (useful for testing).
-
.resolve_subscriber(subscriber) ⇒ Class?
Resolve a subscriber to its current class object.
-
.subscribe(pattern, subscriber = nil, options = {}) {|event| ... } ⇒ void
Subscribe to an event pattern.
-
.subscriptions ⇒ Array<Spree::Events::Registry::Subscription>
List all subscriptions.
-
.unsubscribe(pattern, subscriber) ⇒ Boolean
Unsubscribe from an event pattern.
Class Attribute Details
.log_subscription ⇒ Object
Reference to the AS::N subscription created by Spree::EventLogSubscriber. Stored here (on a module in lib/, not reloaded by Zeitwerk) so that code reloads in development don’t orphan the subscription and cause events to be logged multiple times.
35 36 37 |
# File 'lib/spree/events.rb', line 35 def log_subscription @log_subscription end |
Class Method Details
.activate! ⇒ Object
Activate the event system (called during Rails initialization) Also registers all subscribers from Spree.subscribers This method is idempotent - calling it multiple times has no effect
110 111 112 113 114 115 |
# File 'lib/spree/events.rb', line 110 def activate! return if registry.size > 0 register_subscribers! adapter.activate! end |
.adapter ⇒ Object
Get the adapter instance
The adapter class can be configured via Spree.events_adapter_class Default: Spree::Events::Adapters::ActiveSupportNotifications
103 104 105 |
# File 'lib/spree/events.rb', line 103 def adapter @adapter ||= Spree.events_adapter_class.new(registry) end |
.disable { ... } ⇒ Object
Temporarily disable events within a block
204 205 206 207 208 209 210 |
# File 'lib/spree/events.rb', line 204 def disable previous = Thread.current[:spree_events_disabled] Thread.current[:spree_events_disabled] = true yield ensure Thread.current[:spree_events_disabled] = previous end |
.disable! ⇒ void
This method returns an undefined value.
Globally disable events
Uses a class-level flag that is not affected by per-request cleanup. Useful for disabling events for the entire test suite.
218 219 220 |
# File 'lib/spree/events.rb', line 218 def disable! @globally_disabled = true end |
.enable { ... } ⇒ Object
Temporarily enable events within a block Useful for testing when events are globally disabled
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/spree/events.rb', line 234 def enable previous_global = @globally_disabled previous_thread = Thread.current[:spree_events_disabled] @globally_disabled = false Thread.current[:spree_events_disabled] = false yield ensure @globally_disabled = previous_global Thread.current[:spree_events_disabled] = previous_thread end |
.enable! ⇒ void
This method returns an undefined value.
Globally enable events Useful for testing
248 249 250 |
# File 'lib/spree/events.rb', line 248 def enable! @globally_disabled = false end |
.enabled? ⇒ Boolean
Check if events are enabled
Events can be temporarily disabled using Spree::Events.disable { … } or globally with Spree::Events.disable!
189 190 191 |
# File 'lib/spree/events.rb', line 189 def enabled? !@globally_disabled && !Thread.current[:spree_events_disabled] end |
.patterns ⇒ Array<String>
List all registered subscriber patterns
172 173 174 |
# File 'lib/spree/events.rb', line 172 def patterns registry.patterns end |
.publish(name, payload = {}, metadata = {}) ⇒ Spree::Event
Publish an event to all matching subscribers
48 49 50 |
# File 'lib/spree/events.rb', line 48 def publish(name, payload = {}, = {}) adapter.publish(name, payload, ) end |
.register_subscribers! ⇒ void
This method returns an undefined value.
Register all subscribers from Spree.subscribers
This is called automatically during Rails initialization. Can also be called in tests after reset! to re-register subscribers.
In development, class objects in Spree.subscribers may become stale after code reload (Zeitwerk creates new class objects). We resolve the constant fresh from the class name to ensure we’re using the reloaded class.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/spree/events.rb', line 134 def register_subscribers! return unless defined?(Spree) && Spree.respond_to?(:subscribers) Spree.subscribers&.each do |subscriber| # Resolve the subscriber constant fresh to handle code reload in development # The array may contain stale class objects after Zeitwerk reload resolved_subscriber = resolve_subscriber(subscriber) next unless resolved_subscriber resolved_subscriber.subscription_patterns.each do |pattern| subscribe(pattern, resolved_subscriber, resolved_subscriber.) end end end |
.registry ⇒ Spree::Events::Registry
Get the event registry
93 94 95 |
# File 'lib/spree/events.rb', line 93 def registry @registry ||= Registry.new end |
.reset! ⇒ Object
Reset the event system (useful for testing)
118 119 120 121 122 |
# File 'lib/spree/events.rb', line 118 def reset! adapter.deactivate! if @adapter @registry = nil @adapter = nil end |
.resolve_subscriber(subscriber) ⇒ Class?
Resolve a subscriber to its current class object
In development, Zeitwerk may have reloaded the class, creating a new class object while the old one is still referenced in Spree.subscribers. This method resolves the constant fresh to get the current class.
157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/spree/events.rb', line 157 def resolve_subscriber(subscriber) return subscriber unless Rails.env.development? || Rails.env.test? class_name = subscriber.is_a?(String) ? subscriber : subscriber.name return nil unless class_name class_name.constantize rescue NameError => e Rails.logger.warn "[Spree Events] Could not resolve subscriber #{class_name}: #{e.}" nil end |
.subscribe(pattern, subscriber = nil, options = {}) {|event| ... } ⇒ void
This method returns an undefined value.
Subscribe to an event pattern
74 75 76 77 78 79 |
# File 'lib/spree/events.rb', line 74 def subscribe(pattern, subscriber = nil, = {}, &block) subscriber = block if block_given? raise ArgumentError, 'Must provide a subscriber class, callable, or block' unless subscriber adapter.subscribe(pattern, subscriber, ) end |
.subscriptions ⇒ Array<Spree::Events::Registry::Subscription>
List all subscriptions
179 180 181 |
# File 'lib/spree/events.rb', line 179 def subscriptions registry.all_subscriptions end |
.unsubscribe(pattern, subscriber) ⇒ Boolean
Unsubscribe from an event pattern
86 87 88 |
# File 'lib/spree/events.rb', line 86 def unsubscribe(pattern, subscriber) adapter.unsubscribe(pattern, subscriber) end |