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

加载ActionController::API后添加模块,为何祖先链未更新?

问题原因与解决方案

核心原因

在Rails中,ActionController::API这类核心控制器类加载完成后,其祖先链(ancestors数组)会被冻结或静态缓存,后续动态修改它已引入模块的祖先链时,无法自动同步到ActionController::API的祖先列表中。

而纯Ruby中测试能生效,是因为Ruby原生类和模块的祖先链是动态维护的,没有额外的冻结或缓存逻辑。

对应你的场景:

  • 第一个puts语句触发ActionController::API加载,此时ActionController::ApiRendering还未引入ActionView::Rendering,API的祖先链被固化。
  • 后续给ApiRendering添加Rendering模块,但API的祖先链无法动态更新,所以第二个puts仍返回false。
  • 注释第一个puts后,API会在你修改ApiRendering之后才加载,此时ApiRendering已包含Rendering,所以API的祖先链自动包含该模块,返回true。

解决方案

1. 提前修改模块,避免类加载后操作

将initializer的执行时机提前,确保在ActionController::API加载前就修改ActionController::ApiRendering:

module MyModule
  class Railtie < Rails::Railtie
    # 配置initializer在配置初始化阶段前执行
    initializer "mymodule.initialize", :before => :load_config_initializers do |app|
      if Rails::VERSION::MAJOR >= 5
        module ::ActionController
          module ApiRendering
            include ActionView::Rendering
          end
        end

        # 此时API可能未加载,后续加载时会自动继承修改后的模块
        puts defined?(ActionController::API) ? ActionController::API.ancestors.include?(ActionView::Rendering) : "API 尚未加载"
      end
    end
  end
end

2. 兼容已加载类:修改模块 + 直接补加

如果无法确保initializer执行时机,或者需要兼容ActionController::API被提前加载的场景(比如scout_apm提前加载API类),可以同时修改模块和直接给已加载的API类引入目标模块:

module MyModule
  class Railtie < Rails::Railtie
    initializer "mymodule.initialize" do |app|
      if Rails::VERSION::MAJOR >= 5
        module ::ActionController
          module ApiRendering
            include ActionView::Rendering
          end
        end

        # 若API已加载且未包含目标模块,直接引入
        if defined?(ActionController::API) && !ActionController::API.ancestors.include?(ActionView::Rendering)
          ActionController::API.include(ActionView::Rendering)
        end

        puts ActionController::API.ancestors.include?(ActionView::Rendering)
      end
    end
  end
end

场景补充

scout_apm先引入时触发问题的原因是:这类监控工具会在Rails初始化早期加载ActionController::API以注入监控逻辑,导致你的initializer执行时,API类已完成加载,祖先链被固化,无法同步后续的模块修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:07:01