ruby-on-rails 关于用Zeitwerk自动装弹机在钢轨上重新装弹和发动机的问题

wlzqhblo  于 2022-12-20  发布在  Ruby
关注(0)|答案(1)|浏览(257)

背景:
当我切换到Zeitwerk开发一个使用引擎(thredded)的rails 6.0应用程序时,我遇到了一些重载错误。我也是一个thredded的开发人员,所以在提交任何明显的修复之前,我想完全理解这一点:
我已经读过了:

  • https://guides.rubyonrails.org/autoloading_and_reloading_constants
  • https://guides.rubyonrails.org/engines.html#overriding-models-and-controllers (and implemented these fixes in the main app)
  • https://github.com/fxn/zeitwerk/blob/main/README.md(信息量惊人)
  • https://github.com/fxn/zeitwerk/issues/143
    • 第一个问题(自动加载和引擎的分离)**:引擎是和主应用程序在同一个zeitwerk示例/加载器中自动加载的,还是它们以某种方式单独加载的?也就是说,用Rails.application.reloader.to_prepare do Package 一些代码是否能确保在主应用程序和引擎重新加载之前运行代码。
    • 第二个问题(重新加载引擎代码)**:当主应用程序重新加载时,引擎的常量是否重新加载?(我的理解是肯定的)。
    • 第四个问题(所有这些都要准备)**:有人能解释一下或给我指一下澄清以下两种产品生命周期差异的文档吗?
  • Rails.application.reloader.to_prepare do(并且块是否至少运行一次,即使它在生产环境中急于加载并启用了重新加载)
  • Rails.application.config.to_prepare do
  • SomeEngine::Engine.config.to_prepare do

任何答案都很好。有点长的Q,有多个部分。如果合适的话,我很乐意把它分成多个StackOverflow Q,但它们看起来很有联系。

mwg9r5ms

mwg9r5ms1#

根据上面评论中的讨论和https://github.com/fxn/zeitwerk/issues/240中的讨论回答我对未来的问题。
(1)是的,主自动加载器同时管理应用程序和所有引擎。
(2)是的,当主应用程序重新加载时,引擎的常量也会重新加载。
(3)默认情况下,仅自动加载引擎的app目录中的内容(除非在engines engine.rb中更改config.autoload_paths),并且引擎的顶级常量(在本例中为Thredded模块)通常在app外部的lib中定义(例如lib/thredded.rb)。
(4)大致确定的答案(如有任何更新,欢迎提供)

  • Rails.application.reloader.to_prepare在应用程序启动时(即使是在快速加载时)以及每次重新加载时(在开发中)运行--请参见https://guides.rubyonrails.org/v6.1.0/autoloading_and_reloading_constants.html#autoloading-when-the-application-boots
  • Rails.application.config.to_prepare和SomeEngine::Engine.config.to_prepare在 Boot 时运行,每次重新加载后,请参见https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#use-case-1-during-boot-load-reloadable-code(我假设在reloader.to_prepare之后application.config.to_prepare和... Engine.config.to_prepare的相对顺序将取决于它们的相对加载顺序(请参见https://api.rubyonrails.org/classes/Rails/Engine.html#class-Rails::Engine-label-Loading+priority HT https://stackoverflow.com/a/73982363/109175
  • 此外,我发现您可以定义引擎需要的初始化器(并且只在自动加载之前的 Boot 时运行),方法是
initializer "some explanation of what is for" do
   # code that occurs on initialization 
end

(See https://guides.rubyonrails.org/engines.html#separate-assets-and-precompiling获取此初始值设定项方法的示例)
我发现当一个引擎想要修补另一个引擎时,这对于定义“覆盖”特别有用:

initializer "let the main autoloader ignore this engine's overrides" do
   overrides = root.join("app/overrides")
   Rails.autoloaders.main.ignore(overrides)
end

这与您在主应用中对引擎中自动加载的常量进行monkey-patching时所做的操作类似(https://guides.rubyonrails.org/engines.html#overriding-models-and-controllers)。

相关问题