Help us learn about your current experience with the documentation. Take the survey.

Rails 初始化器

初始化器在 Rails 进程启动时执行。这意味着每次部署时也会执行初始化器。

默认情况下,Rails 会在 config/initializers 中的初始化器加载后加载 Zeitwerk。 在 Zeitwerk 加载前进行自动加载现已弃用,但由于我们在初始化器中使用了大量自动加载的 常量,我们必须将 Zeitwerk 的加载提前到这些初始化器之前。

这样做的一个副作用是,在初始化器中,config.autoload_paths 已经被冻结。

要在 Zeitwerk 加载前运行初始化器,需要将它们放在 config/initializers_before_autoloader 中。 该文件夹中的 Ruby 文件按字母顺序加载,就像默认的 Rails 初始化器一样。

需要这样做的示例包括:

  1. 修改 Rails 的 config.autoload_paths
  2. 更改 Zeitwerk 使用的配置,例如词形变化

初始化器中的数据库连接

理想情况下,不应从 Rails 初始化器中打开数据库连接。从初始化器中打开 数据库连接(例如,检查数据库是否存在,或执行数据库查询)意味着像 db:dropdb:test:prepare 这样的任务会失败,因为活动会话会阻止数据库被删除。

为防止这种情况,我们在路由加载期间阻止数据库连接的打开。这样做会导致错误:

RuntimeError:
  初始化器期间不应调用数据库连接。
# ./config/initializers/00_connection_logger.rb:15:in `new_client'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:112:in `block in read_write'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:184:in `retry_with_backoff'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:111:in `read_write'
# ./lib/gitlab/database/load_balancing/connection_proxy.rb:119:in `write_using_load_balancer'
# ./lib/gitlab/database/load_balancing/connection_proxy.rb:89:in `method_missing'
# ./config/routes.rb:10:in `block in <main>'
# ./config/routes.rb:9:in `<main>'