我正在开发一个Rails 6应用程序和一个Gem。
过去,我使用require_reloader Gem,这样当Gem本地目录中的任何文件更改时,Rails会重新加载该Gem。
随着Zeitwerk成为Rails 6中的新加载器,这个Gem似乎不再起作用了。
所以我的问题是:有什么权威的方法可以同时开发Gem和Rails 6应用程序,以便对Gem文件所做的更改在Rails中自动可见?
我正在开发一个Rails 6应用程序和一个Gem。
过去,我使用require_reloader Gem,这样当Gem本地目录中的任何文件更改时,Rails会重新加载该Gem。
随着Zeitwerk成为Rails 6中的新加载器,这个Gem似乎不再起作用了。
所以我的问题是:有什么权威的方法可以同时开发Gem和Rails 6应用程序,以便对Gem文件所做的更改在Rails中自动可见?
假设,这个 gem 文件夹是
~/rails/foo_gem
~/rails/bar_app
foo_gem.rb
中定义的负责加载不同 gem 文件的 zeitwerk 加载器。development.rb
中定义一个新的 zeitwerk 加载器,该加载器配置了 enable_reloading
。foo_gem.rb
中的 Zeitwerk::Loader
# ~/rails/foo_gem/lib/foo_gem.rb
# require 'foo_gem/bar` # Did not work. Instead:
# (a) use zeitwerk:
require "zeitwerk"
loader = Zeitwerk::Loader.new
loader.push_dir File.join(__dir__)
loader.tag = "foo_gem"
loader.setup
# or (b) use autoload:
module FooGem
autoload :Bar, "foo_gem/bar"
end
require
加载 gem 的所有 ruby 文件。这在这里不起作用,因为 zeitwerk 似乎会忽略先前使用 require
加载的文件。相反,我需要为 gem 创建一个单独的 zeitwerk 加载器。enable_reloading
,否则,在使用 gem 时,会启用此 gem 的重新加载,而不仅仅是在开发 gem 时。Zeitwerk::Registry
中找到这个加载器,以便注销它。foo_gem.rb
中使用 zeitwerk 外,也可以像 devise gem 那样使用 autoload
。如果您想支持早于 6 版本的 rails,则这是最佳方法,因为 zeitwerk 需要 rails 6+。在这里使用 autoload
也使下一节中的步骤 1 不必要。development.rb
文件中的 Zeitwerk::Loader
。# ~/rails/bar_app/config/environments/development.rb
# 1. Unregister the zeitwerk loader defined in foo_gem.rb that handles loading
# the different gem files.
#
Zeitwerk::Registry.loaders.detect { |l| l.tag == "foo_gem" }.unregister
# 2. Define a new zeitwerk loader in the development.rb of the app
# that is configured with enable_reloading.
#
gem_root_path = Pathname.new(Gem.loaded_specs["foo_gem"].full_gem_path)
gem_loader = Zeitwerk::Loader.new
gem_loader.push_dir gem_root_path.join("lib")
gem_loader.enable_reloading
gem_loader.setup
# 3. Setup a file-system watcher and trigger a reload when a gem file changes.
#
Listen.to gem_root_path.join("lib"), only: /\.rb$/ do
gem_loader.reload
end.start
"foo_gem"
的加载器。enable_reloading
。因此,在使用 rails server
、rails console
或运行规范时,可以重新加载 gem 文件。ActiveSupport::FileUpdateChecker
工作。取而代之,我使用了 listen gem 作为文件系统监视器。rails server
、rails console
或 bar_app 的规范时,foo_gem
的 gem 文件在被编辑后会被重新加载,这意味着不再需要重新启动 rails server
来获取更改。