You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails从5.0升级至7.0.4.3后遇NameError:未初始化常量Api

解决Rails 7升级后uninitialized constant Api (NameError)问题

问题场景

将Ruby从2.6.6升级到3.2.2、Rails从5.x升级到7.0.4.3后,启动rails s时出现以下错误:

=> Booting Puma
=> Rails 7.0.4.3 application starting in development
=> Run `bin/rails server --help` for more startup options
Exiting
/mnt/c/Users/akaram/Desktop/Ruby/hire-right-integration/config/initializers/api_v1_log.rb:2:in `<top (required)>': uninitialized constant Api (NameError)

  Api::V1::Log.logger = Logger.new(Api::V1::Log::LogFile)
         ^^^^^

涉及核心文件:

  • config/initializers/api_v1_log.rb:
unless ENV['ASSET_PRECOMPILE'].present?
  Api::V1::Log.logger = Logger.new(Api::V1::Log::LogFile)
  Api::V1::Log.logger.level = 'info'
end
  • app/models/api/v1/log.rb:
module Api::V1
  class Log
    LogFile = Rails.root.join("log", "api_v1_#{Rails.env}.log")
    class << self
      cattr_accessor :logger
      delegate :debug, :info, :warn, :error, :fatal, :to => :logger
    end
  end
end
  • 已在config/application.rb添加配置:
config.eager_load = true 
config.autoload_paths << Rails.root.join('app')
config.autoload_paths += %W(#{config.root}/app/models/api/v1/)

问题原因

Rails 7默认采用Zeitwerk作为自动加载器,替换了Rails 5的经典自动加载机制,核心冲突点:

  1. 初始化器执行时机早于模型类的自动加载流程,此时Api::V1::Log常量尚未被加载
  2. module Api::V1的嵌套定义方式不符合Zeitwerk的规范,导致模块无法被自动识别
  3. 手动添加的autoload_paths在Zeitwerk机制下优先级极低,甚至不生效

解决方案

方案1:手动加载模型文件到初始化器

直接在初始化器中提前加载目标模型文件,确保常量存在:

unless ENV['ASSET_PRECOMPILE'].present?
  # 手动加载Log模型文件
  require Rails.root.join('app/models/api/v1/log')
  Api::V1::Log.logger = Logger.new(Api::V1::Log::LogFile)
  # 注意:将字符串'info'改为Logger常量,新版Ruby/Rails不支持字符串设置级别
  Api::V1::Log.logger.level = Logger::INFO
end

方案2:延迟初始化到Rails加载完成后

利用config.after_initialize钩子,在所有模型加载完成后再执行初始化逻辑:
修改config/initializers/api_v1_log.rb为:

Rails.application.config.after_initialize do
  next if ENV['ASSET_PRECOMPILE'].present?

  Api::V1::Log.logger = Logger.new(Api::V1::Log::LogFile)
  Api::V1::Log.logger.level = Logger::INFO
end

方案3:适配Zeitwerk自动加载规范(推荐长期方案)

Zeitwerk要求每个模块对应独立的目录和文件,按以下步骤调整:

  1. 创建app/models/api.rb定义Api模块:
module Api
end
  1. 创建app/models/api/v1.rb定义Api::V1模块:
module Api::V1
end
  1. (可选)将app/models/api/v1/log.rb的模块定义改为嵌套式(更符合规范):
module Api
  module V1
    class Log
      LogFile = Rails.root.join("log", "api_v1_#{Rails.env}.log")
      class << self
        cattr_accessor :logger
        delegate :debug, :info, :warn, :error, :fatal, :to => :logger
      end
    end
  end
end
  1. 移除config/application.rb中手动添加的autoload_paths配置,Zeitwerk默认会自动扫描app目录下的所有文件。

内容的提问来源于stack exchange,提问作者AntonioKaram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:36:28