19

我正在使用一个初始化程序,它通过将一些应用程序问题包含到第三方库中来对应用程序进行一些猴子修补。基本上:

# config/initializers/my_initializer.rb

class SomeExternalLib
  include MyConcern1
  include MyConcern2
end

这在 Rails 5.2.3 中运行良好,但在升级到 Rails 6 时收到以下弃用消息:

弃用警告:初始化自动加载常量 MyConcern1 和 MyConcern2。

能够做到这一点已被弃用。在未来的 Rails 版本中,初始化期间的自动加载将成为一个错误条件。

重新加载不会重新启动应用程序,因此在初始化期间执行的代码不会再次运行。因此,例如,如果您重新加载 ApplicationHelper,预期的更改将不会反映在该陈旧的 Module 对象中。

这些自动加载的常量已被卸载。

请查看“自动加载和重新加载常量”指南以获取解决方案。(从 /Users/myuser/code/myapp/config/environment.rb:7 调用)

我的担忧在 app/controllers/concerns/ 中。经过一番调查,我发现该路径没有被自动加载,但我不知道如何使 Zeitwerk(Rails 6 的新自动加载器)动态加载它。我尝试遵循此处描述的 STI 自动加载模式,但没有运气。知道如何解决此弃用警告吗?

4

2 回答 2

20

正如@Glyoko 的回答所描述的,使用require依赖项可以防止在初始化程序中自动加载。但是,正如@Puhlze 在他的评论中提到的那样,这样做会导致重新加载过程中出现问题。

我偶然发现了这篇文章中使用的另Rails.configuration.to_prepare一种方法

一个例子是:

# config/initializers/my_initializer.rb

Rails.configuration.to_prepare do
  class SomeExternalLib
    include MyConcern1
    include MyConcern2
  end
end

请注意,这在开发中的每个请求之前运行,但在生产中的预加载之前仅运行一次。

编辑:它似乎也适用于重新加载。

于 2020-01-29T16:37:01.540 回答
10

如果我更仔细地阅读错误消息会有所帮助:

在未来的 Rails 版本中,初始化期间的自动加载将成为一个错误条件。

有关更改的讨论在这里,指南在这里

简而言之,不应该在初始化程序中完成自动加载,这将被逐步淘汰。解决方案是:1)不要使用需要在初始化程序中自动加载的东西(显然是首选),或者 2)在初始化程序中明确需要依赖项。

所以我会这样做:

# config/initializers/my_initializer.rb

require 'my_concern1'
require 'my_concern2'

class SomeExternalLib
  include MyConcern1
  include MyConcern2
end
于 2019-06-03T23:56:24.933 回答