Ruby 模块在前置后不是祖先

问题描述 投票:0回答:1

我正在为 Rails (6.1.7) 项目 Foreman(v3.5.1;基于 Foreman 插件模板)开发一个 插件,并面临我的一个模块 (

DnsInterfaceExtensions
) 的问题) 应该放在 Foreman 模块前面。问题是,即使在
prepend
之后,
DnsInterfaceExtensions
也不会 not 显示为 Foreman 的
DnsInterface
的祖先(在 Rails 控制台中):

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
,显然它被执行了,但是新的类方法没有添加到
DnsInterface
,模块的常量
:RECORD_TYPE
覆盖也没有。如果 Ruby 没有任何错误,我不知道这个结果的原因是什么。有什么想法吗?

感谢您的宝贵时间,
泽维尔。


编辑-1

我刚刚发现任何延伸的空心模块都会出现同样的现象

ActiveSupport::Concern

irb(main):001:0> (DnsInterface.prepend Module.new { extend ActiveSupport::Concern }).ancestors
=> [DnsInterface]

编辑-2

然而,在这个SO回答中,@Marian13说Rails 6.1.7应该支持前置。然而,当两个模块扩展ActiveSupport::Concern时,它不起作用

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]
但是,如果不在我的模块中扩展 

ActiveSupport::Concern

,我就无法使用 
prepended
class_methods
 块。


编辑-3

我想这整个事情都会出错,因为

Concern的class_methods

定义了模块:ClassMethods
。因此,通过在两个模块中扩展 
ActiveSupport::Concern
,每个模块都有自己的 
:ClassMethods
,以某种方式阻止建立祖先?

ruby-on-rails ruby include monkeypatching theforeman
1个回答
1
投票
看来我对两个模块扩展

ActiveSupport::Concern

的预感是正确的。通过模仿 Concern 的语法糖,
在前面添加一个名为 ClassMethods 的嵌套模块 not
,事情会变得更好。

module ForemanCnames::DnsInterfaceExtensions def self.prepended(base) class << base prepend CnameClassMethods end end module CnameClassMethods def dns_cname_record_attrs end end end
irb(main):001:0> DnsInterface.ancestors
=> [ForemanCnames::DnsInterfaceExtensions, DnsInterface]

irb(main):002:0> DnsInterface.methods.filter { |m| m.to_s =~ /cname/ }
=> [:dns_cname_record_attrs]
虽然我没能覆盖常量。

irb(main):003:0> DnsInterface::RECORD_TYPES => [:a, :aaaa, :ptr4, :ptr6]
...但这是一个不同的问题。


编辑-1

我想我必须撤回这个答案,因为它没有达到我想要的......

irb(main):001:0> DnsInterface.method(:dns_feasible?).source_location => ["/usr/local/share/gems/gems/foreman_cnames-0.0.1/app/models/foreman_cnames/dns_interface_extensions.rb", 15] irb(main):002:0> DnsInterface.instance_method(:dns_feasible?).source_location => ["/usr/share/foreman/app/models/concerns/dns_interface.rb", 22]
虽然添加了 

DnsInterfaceExtension

 的方法,但它们并没有覆盖 
DnsInterface
 已有的内容。

© www.soinside.com 2019 - 2024. All rights reserved.