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
|
||||
end
|
||||
|
||||
def test_current_scope_is_reset
|
||||
Object.const_set :UnloadablePost, Class.new(ActiveRecord::Base)
|
||||
UnloadablePost.current_scope = UnloadablePost.all
|
||||
def test_before_remove_const_resets_the_current_scope
|
||||
# Done this way because a class cannot be defined in a method using the
|
||||
# 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
|
||||
klass = UnloadablePost
|
||||
assert_not_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
|
||||
ActiveSupport::Dependencies.remove_unloadable_constants!
|
||||
assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(klass)
|
||||
ReloadableModel.before_remove_const
|
||||
|
||||
assert_nil ActiveRecord::Scoping::ScopeRegistry.current_scope(ReloadableModel)
|
||||
ensure
|
||||
Object.class_eval { remove_const :UnloadablePost } if defined?(UnloadablePost)
|
||||
Object.send(:remove_const, :ReloadableModel)
|
||||
end
|
||||
|
||||
def test_marshal_round_trip
|
||||
|
|
|
@ -89,7 +89,13 @@ module ActiveSupport
|
|||
autoloader.do_not_eager_load(autoload_path) unless eager_load?(autoload_path)
|
||||
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)
|
||||
end
|
||||
|
||||
|
|
|
@ -341,6 +341,34 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase
|
|||
assert_equal :no_op, deps.unhook!
|
||||
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
|
||||
boot
|
||||
|
||||
|
|
Loading…
Reference in a new issue