mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Implement support for before_remove_const in zeitwek mode
This needs Zeitwerk 2.5 for the on_unload hook.
This commit is contained in:
parent
6b49f33054
commit
36e716cdc1
3 changed files with 45 additions and 10 deletions
|
@ -1266,17 +1266,18 @@ class BasicsTest < ActiveRecord::TestCase
|
||||||
assert_equal c1, c2
|
assert_equal c1, c2
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_current_scope_is_reset
|
def test_before_remove_const_resets_the_current_scope
|
||||||
Object.const_set :UnloadablePost, Class.new(ActiveRecord::Base)
|
# Done this way because a class cannot be defined in a method using the
|
||||||
UnloadablePost.current_scope = UnloadablePost.all
|
# class keyword.
|
||||||
|
Object.const_set(:ReloadableModel, Class.new(ActiveRecord::Base))
|
||||||
|
ReloadableModel.current_scope = ReloadableModel.all
|
||||||
|
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(ReloadableModel) # precondition
|
||||||
|
|
||||||
UnloadablePost.unloadable
|
ReloadableModel.before_remove_const
|
||||||
klass = UnloadablePost
|
|
||||||
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
|
assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(ReloadableModel)
|
||||||
ActiveSupport::Dependencies.remove_unloadable_constants!
|
|
||||||
assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
|
|
||||||
ensure
|
ensure
|
||||||
Object.class_eval { remove_const :UnloadablePost } if defined?(UnloadablePost)
|
Object.send(:remove_const, :ReloadableModel)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_marshal_round_trip
|
def test_marshal_round_trip
|
||||||
|
|
|
@ -89,7 +89,13 @@ module ActiveSupport
|
||||||
autoloader.do_not_eager_load(autoload_path) unless eager_load?(autoload_path)
|
autoloader.do_not_eager_load(autoload_path) unless eager_load?(autoload_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
Rails.autoloaders.main.enable_reloading if enable_reloading
|
if enable_reloading
|
||||||
|
Rails.autoloaders.main.enable_reloading
|
||||||
|
Rails.autoloaders.main.on_unload do |_cpath, value, _abspath|
|
||||||
|
value.before_remove_const if value.respond_to?(:before_remove_const)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Rails.autoloaders.each(&:setup)
|
Rails.autoloaders.each(&:setup)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -341,6 +341,34 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase
|
||||||
assert_equal :no_op, deps.unhook!
|
assert_equal :no_op, deps.unhook!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "reloading invokes before_remove_const" do
|
||||||
|
$before_remove_const_invoked = false
|
||||||
|
|
||||||
|
app_file "app/models/foo.rb", <<~RUBY
|
||||||
|
# While the most common use case is classes/modules, the contract does not
|
||||||
|
# require values to be so. Let's weaken the test down to Object.new.
|
||||||
|
Foo = Object.new
|
||||||
|
def Foo.before_remove_const
|
||||||
|
$before_remove_const_invoked = true
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
app_file "app/models/bar.rb", <<~RUBY
|
||||||
|
# This object does not implement before_remove_const. We define it to make
|
||||||
|
# sure reloading does not raise. That is, it does not blindly invoke the
|
||||||
|
# hook on all unloaded objects.
|
||||||
|
Bar = Object.new
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
boot
|
||||||
|
|
||||||
|
assert Foo
|
||||||
|
assert Bar
|
||||||
|
ActiveSupport::Dependencies.clear
|
||||||
|
|
||||||
|
assert $before_remove_const_invoked
|
||||||
|
end
|
||||||
|
|
||||||
test "autoloaders.logger=" do
|
test "autoloaders.logger=" do
|
||||||
boot
|
boot
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue