diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec4eb4..4adddd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.18.1 +* Fix issue where only direct dependencies of `Current` and `CurrentInstance` classes are cleared. + ## 0.18.0 * Add better support for registry dependencies in a development environment where classes may be reloaded. * Add a `global_context_mutually_dependent_on` method to support registering bidirectional references. diff --git a/lib/rails_multitenant/global_context_registry/current.rb b/lib/rails_multitenant/global_context_registry/current.rb index 5708be7..822804c 100644 --- a/lib/rails_multitenant/global_context_registry/current.rb +++ b/lib/rails_multitenant/global_context_registry/current.rb @@ -34,8 +34,9 @@ def current! current || raise("No current #{name} set") end - def clear_current! + def clear_current!(cleared = nil) GlobalContextRegistry.delete(current_registry_obj) + __clear_dependents!(cleared) end def as_current(object) @@ -73,8 +74,13 @@ def __current_default end end - def __clear_dependents! - GlobalContextRegistry.send(:dependencies_for, __key_class).each(&:clear_current!) + def __clear_dependents!(initial_cleared = nil) + GlobalContextRegistry.send(:dependencies_for, __key_class).tap do |dependencies| + next unless dependencies.present? + + (cleared = initial_cleared || []) << self + dependencies.each { |obj| obj.clear_current!(cleared) unless cleared.include?(obj) } + end end def __key_class diff --git a/lib/rails_multitenant/global_context_registry/current_instance.rb b/lib/rails_multitenant/global_context_registry/current_instance.rb index 138865b..ab4794a 100644 --- a/lib/rails_multitenant/global_context_registry/current_instance.rb +++ b/lib/rails_multitenant/global_context_registry/current_instance.rb @@ -60,15 +60,22 @@ def as_current(model) self.current = old_model end - def clear_current! + def clear_current!(cleared = nil) GlobalContextRegistry.delete(current_instance_registry_obj) + __clear_dependents!(cleared) end private - def __clear_dependents! + def __clear_dependents!(initial_cleared = nil) key_class = respond_to?(:base_class) ? base_class : self - GlobalContextRegistry.send(:dependencies_for, key_class).each(&:clear_current!) + + GlobalContextRegistry.send(:dependencies_for, key_class).tap do |dependencies| + next unless dependencies.present? + + (cleared = initial_cleared || []) << self + dependencies.each { |obj| obj.clear_current!(cleared) unless cleared.include?(obj) } + end end def current_instance_registry_id diff --git a/lib/rails_multitenant/version.rb b/lib/rails_multitenant/version.rb index 9358f46..1a2afa1 100644 --- a/lib/rails_multitenant/version.rb +++ b/lib/rails_multitenant/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module RailsMultitenant - VERSION = '0.18.0' + VERSION = '0.18.1' end diff --git a/spec/rails_multitenant/global_context_registry/current_spec.rb b/spec/rails_multitenant/global_context_registry/current_spec.rb index b4f956a..ef309cf 100644 --- a/spec/rails_multitenant/global_context_registry/current_spec.rb +++ b/spec/rails_multitenant/global_context_registry/current_spec.rb @@ -15,10 +15,15 @@ def initialize(id: :default) before do stub_const('SubClass', Class.new(TestClass)) stub_const('DependentClass', dependent_class) + stub_const('CyclicallyDependentClass1', cyclically_dependent_class1) + stub_const('CyclicallyDependentClass2', cyclically_dependent_class2) stub_const('BiDependentClass', bidependent_class) stub_const('NoDefaultTestClass', no_default_test_class) DependentClass.global_context_dependent_on TestClass + DependentClass.global_context_dependent_on CyclicallyDependentClass2 + CyclicallyDependentClass1.global_context_dependent_on DependentClass + CyclicallyDependentClass2.global_context_dependent_on CyclicallyDependentClass1 BiDependentClass.global_context_mutually_dependent_on TestClass end @@ -29,6 +34,20 @@ def initialize(id: :default) end end + let(:cyclically_dependent_class1) do + Class.new do + include RailsMultitenant::GlobalContextRegistry::Current + provide_default { new } + end + end + + let(:cyclically_dependent_class2) do + Class.new do + include RailsMultitenant::GlobalContextRegistry::Current + provide_default { new } + end + end + let(:bidependent_class) do Class.new do include RailsMultitenant::GlobalContextRegistry::Current @@ -73,8 +92,13 @@ def initialize(id: :default) it "clears dependencies" do dependent = DependentClass.current + cyclically_dependent1 = CyclicallyDependentClass1.current + cyclically_dependent2 = CyclicallyDependentClass1.current + TestClass.current = TestClass.new - expect(dependent_class.current).not_to equal(dependent) + expect(DependentClass.current).not_to equal(dependent) + expect(CyclicallyDependentClass1.current).not_to equal(cyclically_dependent1) + expect(CyclicallyDependentClass2.current).not_to equal(cyclically_dependent2) end it "clears bidirectional dependencies" do