在开发 gem 时,我经常使用一个需要 gem 的虚拟 rails 应用程序,以便在我进行时尝试 gem 更改。此外,我使用相同的虚拟应用程序进行集成测试。
通常,我有宝石
~/rails/foo_gem
以及相关的虚拟应用程序:
~/rails/foo_gem/spec/dummy_app
使用zeitwerk代码加载器,我如何配置虚拟应用程序不仅可以在更改时重新加载虚拟应用程序 ruby 文件,还可以获取对 gem 文件的更改?否则,在开发 gem 时,我必须为 gem 文件的每次更改重新加载 dummy-app rails 服务器。
# ~/rails/foo_gem/spec/dummy_app/config/environments/development.rb
config.cache_classes = false
config.eager_load = false
# TODO: Add ~/rails/foo_gem/lib to the list
# of watched and auto-reloaded directories.
不工作:config.autoload_paths
# ~/rails/foo_gem/spec/dummy_app/config/environments/development.rb
gem_root_path = Pathname.new(File.expand_path(Rails.root.join("../..")))
config.autoload_paths << gem_root_path.join("lib")
我尝试将 gem 添加到自动加载路径,但代码不会在文件系统更改时重新加载。
没用:Zeitwerk::Loader
有enable_reloading
# ~/rails/foo_gem/spec/dummy_app/config/environments/development.rb
gem_root_path = Pathname.new(File.expand_path(Rails.root.join("../..")))
gem_loader = Zeitwerk::Loader.new
gem_loader.push_dir gem_root_path.join("lib")
gem_loader.enable_reloading
gem_loader.log!
gem_loader.setup
添加单独的 zeitwerk 加载程序没有帮助;据我所知,加载程序没有文件系统观察程序;所以需要调用gem_loader.reload
才能重新加载 gem 类。
没用:Zeitwerk::Loader#reload
有require
如果 gem 中需要 gem 的文件,例如
# ~/rails/foo_gem/lib/foo_gem.rb
require 'foo_gem/bar`
然后该文件~/rails/foo_gem/lib/foo_gem/bar.rb
被Zeitwerk::Loader
. 调用gem_loader.reload
不会重新加载此文件。
没有用:Zeitwerk::Loader#reload
使用 zeitwerk 加载器来加载 gem 文件
如果 gem 的文件不是手动需要的,而是使用不同的 zeitwerk 加载器,例如
# ~/rails/foo_gem/lib/foo_gem.rb
require "zeitwerk"
loader = Zeitwerk::Loader.new
loader.push_dir(__dir__)
loader.setup
然后目录~/rails/foo_gem/lib
由两个独立的 zeitwerk 加载器管理:loader
infoo_gem.rb
和gem_loader
in development.rb
。这显然是 zeitwerk 不允许的,它抱怨Zeitwerk::Error
:
loader ...想要管理目录~/rails/foo_gem/lib,该目录已经由...管理
不工作:ActiveSupport::FileUpdateChecker
# ~/rails/foo_gem/spec/dummy_app/config/environments/development.rb
gem_root_path = Pathname.new(File.expand_path(Rails.root.join("../..")))
gem_loader = Zeitwerk::Loader.new
gem_loader.push_dir gem_root_path.join("lib")
gem_loader.enable_reloading
gem_loader.log!
gem_loader.setup
gem_files = gem_root_path.glob("lib/**/*.rb")
gem_update_checker = ActiveSupport::FileUpdateChecker.new(gem_files) do
gem_loader.reload # This line is never executed
end
ActiveSupport::Reloader.to_prepare do
gem_update_checker.execute_if_updated
end
我尝试使用ActiveSupport::FileUpdateChecker
来监视更改,但是,至少在我的 dockerized 设置中,重新加载代码的块永远不会执行。