From 64ce0d8f66fb19b2792889883606561b85eed78d Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Mon, 17 Jun 2019 19:05:35 +0200 Subject: [PATCH] Support class reloading for Event Subscribers Before this change, editing an instance of Spree::Event::Subscriber would result in not being reloaded or being subscribed twice. With this change each includer of Event::Subscriber is registered by its name and later unsubscribed just before class unload (using old module instance), then resubscribed after the new code is loaded. --- core/lib/spree/core/engine.rb | 11 +++++++++-- core/lib/spree/event.rb | 6 ++++++ core/lib/spree/event/configuration.rb | 8 ++++++++ core/spec/lib/spree/event_spec.rb | 26 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/core/lib/spree/core/engine.rb b/core/lib/spree/core/engine.rb index 4e3f55f8182..58645267d38 100644 --- a/core/lib/spree/core/engine.rb +++ b/core/lib/spree/core/engine.rb @@ -44,8 +44,15 @@ class Engine < ::Rails::Engine Migrations.new(config, engine_name).check end - initializer 'spree.core.mailer_subscriber' do - Spree::MailerSubscriber.subscribe! + # Setup Event Subscribers + initializer 'spree.core.initialize_subscribers' do |app| + app.reloader.to_prepare do + Spree::Event.subscribers.each(&:subscribe!) + end + + app.reloader.before_class_unload do + Spree::Event.subscribers.each(&:unsubscribe!) + end end # Load in mailer previews for apps to use in development. diff --git a/core/lib/spree/event.rb b/core/lib/spree/event.rb index 21f37f5ea8d..2378462cab1 100644 --- a/core/lib/spree/event.rb +++ b/core/lib/spree/event.rb @@ -98,6 +98,12 @@ def suffix Spree::Config.events.suffix end + # @!attribute [r] subscribers + # @return [Array] A list of subscribers used to support class reloading for Spree::Event::Subscriber instances + def subscribers + Spree::Config.events.subscribers + end + private def name_with_suffix(name) diff --git a/core/lib/spree/event/configuration.rb b/core/lib/spree/event/configuration.rb index 4190c714d50..ef8d80b0c5f 100644 --- a/core/lib/spree/event/configuration.rb +++ b/core/lib/spree/event/configuration.rb @@ -1,8 +1,16 @@ # frozen_string_literal: true +require 'spree/core/class_constantizer' + module Spree module Event class Configuration + def subscribers + @subscribers ||= ::Spree::Core::ClassConstantizer::Set.new.tap do |set| + set << 'Spree::MailerSubscriber' + end + end + attr_writer :adapter, :suffix def adapter diff --git a/core/spec/lib/spree/event_spec.rb b/core/spec/lib/spree/event_spec.rb index 84f95342982..26cfdd4f472 100644 --- a/core/spec/lib/spree/event_spec.rb +++ b/core/spec/lib/spree/event_spec.rb @@ -89,4 +89,30 @@ end end end + + describe '.subscribers' do + let(:subscriber) { instance_double(Module, 'Subscriber') } + let(:subscriber_name) { instance_double(String, 'Subscriber name') } + + before do + described_class.subscribers.clear + allow(subscriber).to receive(:name).and_return(subscriber_name) + allow(subscriber_name).to receive(:constantize).and_return(subscriber) + allow(subscriber_name).to receive(:to_s).and_return(subscriber_name) + end + + it 'accepts the names of constants' do + Spree::Config.events.subscribers << subscriber_name + + expect(described_class.subscribers.to_a).to eq([subscriber]) + end + + it 'discards duplicates' do + described_class.subscribers << subscriber_name + described_class.subscribers << subscriber_name + described_class.subscribers << subscriber_name + + expect(described_class.subscribers.to_a).to eq([subscriber]) + end + end end