Rails6:更改时自动重新加载本地gem



我正在并行开发一个Rails 6应用程序和一个Gem。

在过去,我使用require_reloader Gem,这样当Gem的本地目录中的任何文件发生变化时,Rails都会重新加载Gem。

随着Zeitwerk成为Rails6中的新加载程序,这个Gem似乎不再工作了。

因此,我的问题是:并行开发Gem和Rails6应用程序的规范方法是什么,这样对Gem文件所做的更改就可以在Rails中自动可见?

我也没有找到这个问题的规范解决方案,但在Rails:dummy应用程序中使用的自动重新加载gem文件的上下文中,我找到了一个解决方法:

假设gem文件夹是

~/rails/foo_gem

rails-6-app文件夹为:

~/rails/bar_app

要在文件系统更改时在应用程序中重新加载gem代码,我需要执行三个步骤:

  1. 注销foo_gem.rb中定义的zeitwerk加载程序,该加载程序负责加载不同的gem文件
  2. 在配置了enable_reloading的应用程序的development.rb中定义一个新的zeitwerk加载程序
  3. 设置一个文件系统观察程序,并在gem文件更改时触发重新加载

Zeitwerk::Loaderfoo_gem.rb

# ~/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

注:

  • 在过去,我刚刚从一种类似于gem的索引文件中加载了带有require的gem的所有ruby文件,这里是foo_gem.rb。这在这里不起作用,因为zeitwerk似乎忽略了以前用require加载的文件。相反,我需要为gem创建一个单独的zeitwerk加载程序
  • 这个加载程序没有enable_reloading,因为否则,无论何时使用gem,都会为这个gem启用重新加载,而不仅仅是在开发gem时
  • 我给了这个加载程序一个tag,它允许稍后在Zeitwerk::Registry中找到这个加载程序,以便取消注册
  • 不在foo_gem.rb中使用zeitwerk,也可以像设计gem那样在那里使用autoload。如果您想支持早于6的rails版本,这是最好的方法,因为zeitwerk需要rails6+。在这里使用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

注:

  • Zeitwerk不允许两个加载器管理相同的文件。因此,我需要注销先前定义的标记为"foo_gem"的加载程序
  • 应用程序中使用的新加载程序具有enable_reloading。因此,当将应用程序与rails serverrails console一起使用时,或者当运行规范时,可以重新加载gem文件
  • zeitwerk不会自动重新加载gem文件。需要一个文件系统观察程序来触发文件系统更改时的重新加载。我没能使ActiveSupport::FileUpdateChecker工作。相反,我使用了listenerm作为文件系统观察程序

使用此设置,当使用rails serverrails console或bar_app的规范时,foo_gem的gem文件在编辑后会重新加载,这意味着不再需要重新启动rails server来获取更改。

但是,我觉得这种变通方法不是很方便。

相关内容

  • 没有找到相关文章

最新更新