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

Ruby模块执行prepend后无法成为祖先的问题求助

Foreman插件开发中ActiveSupport::Concern模块prepend失效问题

我基于Rails 6.1.7的Foreman(v3.5.1)项目开发插件(使用Foreman Plugin Template),遇到以下问题:

自定义模块ForemanCnames::Concerns::DnsInterfaceExtensions需要prepend到Foreman的DnsInterface模块中,但执行prepend后,该模块并未出现在DnsInterface的祖先列表里。控制台测试如下:

irb(main):001:0> DnsInterface.ancestors
=> [DnsInterface]

irb(main):002:0> DnsInterface.prepend ForemanCnames::Concerns::DnsInterfaceExtensions
=> DnsInterface

irb(main):003:0> DnsInterface.ancestors
=> [DnsInterface]

irb(main):005:0> DnsInterface.prepend Module.new
=> DnsInterface

irb(main):006:0> DnsInterface.ancestors
=> [#<Module:0x0000558ef346d9d0>, DnsInterface]

我给DnsInterfaceExtensions定义了prepended方法,该方法确实被执行,但新添加的类方法并未生效,模块常量:RECORD_TYPE也未被覆盖,Ruby没有抛出任何错误。

后续排查发现

  • 编辑1:任何继承ActiveSupport::Concern的空模块都会出现同样现象:

    irb(main):001:0> (DnsInterface.prepend Module.new { extend ActiveSupport::Concern }).ancestors
    => [DnsInterface]
    
  • 编辑2:测试发现两个都继承ActiveSupport::Concern的模块互相prepend时,祖先列表不会更新;但普通模块prepend正常。如果不继承ActiveSupport::Concern,就无法使用prepended回调或class_methods块:

    irb(main):001:1* module M
    irb(main):002:1*   extend ActiveSupport::Concern
    irb(main):003:0> end
    => M
    
    irb(main):004:1* module N
    irb(main):005:1*   extend ActiveSupport::Concern
    irb(main):006:0> end
    => N
    
    irb(main):007:0> (M.prepend N).ancestors
    => [M]
    
  • 编辑3:猜测问题根源可能是ActiveSupport::Concern的class_methods会定义:ClassMethods模块,当两个模块都继承ActiveSupport::Concern时,各自的:ClassMethods可能阻碍了祖先关系的建立?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:12:45