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

Rails 6.1应用初始化后FeatureFlags配置object_id变更问题

问题原因说明

Rails 6默认使用Zeitwerk作为自动加载器,你的问题本质是开发环境下的自动重载机制导致的:

  1. Rails开发环境默认config.cache_classes = false,所有Zeitwerk托管的自动加载常量,在每次请求结束后都会被卸载,下次引用时会重新加载类文件。
  2. 你的FeatureFlags类放在app/lib下,属于Zeitwerk的自动加载路径。初始化器是Rails启动阶段执行的,这时候引用FeatureFlags会触发Zeitwerk第一次加载这个类,你在初始化器里给@configuration赋值完成,得到第一个object_id的实例。
  3. 当第一次请求到来时,之前加载的FeatureFlags常量已经被Zeitwerk卸载,调用FeatureFlags.enabled?时会重新加载整个feature_flags.rb文件,类级别的@configuration实例变量会被重置,自然就得到了新的object_id,之前的配置也全部丢失。
  4. 你手动加require 'feature_flags'之后,这个类是通过Ruby原生的require机制加载的,Zeitwerk不会把它标记为自动重载的托管常量,所以请求阶段不会被卸载,实例就可以保留。

疑问解答

  • 为什么Zeitwerk自动加载了还需要手动require?
    不是Zeitwerk没加载,而是它默认会在开发环境重载自动加载路径下的常量。你初始化阶段的类实例和请求阶段的类已经不是同一个了,自然配置会丢失。手动require相当于告诉Zeitwerk这个类不要管重载的事,自然就不会出问题。

  • 手动require是不是正确的实现方式?
    对于不需要热重载的工具类来说,这个做法完全可用,也不会有什么副作用。如果想要更规范的处理,也可以选择下面的方案:

    • 把FeatureFlags类移到lib目录下,不要放在自动重载的app/lib里,在config/application.rb中把lib加入全局加载路径,这样默认就不会被重载
    • 如果一定要放在app/lib下,可以配置Zeitwerk忽略这个文件的重载:Rails.autoloaders.main.ignore(Rails.root.join('app/lib/feature_flags.rb'))
    • 生产环境默认config.cache_classes = true,不会触发常量重载,就算不加手动require也不会出现配置丢失的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:15:03