Ruby 在其他模块中包含一个模块

Ruby 在其他模块中包含一个模块,ruby,Ruby,如何将模块B包含在A中,以便已经包含模块A的类也可以从模块B中获取方法?您应该在类C之前将B包含在A中;包括:;结束 module A; def a; end; end module B; def b; end; end class C; include A; end module A; include B; end class D; include A; end C.new.b # undefined method error D.new.b # nil C.ancestors # [

如何将模块B包含在A中,以便已经包含模块A的类也可以从模块B中获取方法?

您应该在类C之前将B包含在A中;包括:;结束

module A; def a; end; end
module B; def b; end; end

class C; include A; end

module A; include B; end
class D; include A; end

C.new.b # undefined method error
D.new.b # nil

C.ancestors # [C, A, Object...]
D.ancestors # [D, A, B, Object...]
编辑

module A; def a; end; end
module B; def b; end; end


module A; include B; end

class C; include A; end
class D; include A; end

p C.new.b # nil
p D.new.b # nil

p C.ancestors # [C, A, B, Object, Kernel, BasicObject]
p D.ancestors # [D, A, B, Object, Kernel, BasicObject]
你不能

当您
混入
M
到类
C
中时,Ruby将创建一个新类
⟦M′⟧
其方法表指向mixin
M
的方法表,其超类是
C
的超类,然后使该类成为
C
的新超类。对于混合到
M
中的每个mixin,都会重复此操作


请注意,当您将
M
混合到
C
中时,此算法只运行一次。稍后获得
包含
d的模块将不会被考虑。

如前所述,Ruby不是这样工作的-当一个类包含一个模块时,它不会维护对该模块实例的任何引用,因此如果该模块包含其他模块,则已经包含的类将不知道该更改

您可以通过将包含模块的类存储在模块本身中来解决此问题,这样您就可以在模块包含另一个模块时更新这些类,例如:

module A; def a; end; end
module B; def b; end; end

class C; include A; end

module A; include B; end
class D; include A; end

C.send(:include, A)

p C.new.b # nil
p D.new.b # nil

p  C.ancestors # [C, A, Object...]
p D.ancestors # [D, A, B, Object...]
模块A

classI无法更改类包含这些模块的顺序。我正在尝试扩展Rails
ActionDispatch::Routing::UrlFor
模块,该模块已经包含在一些Rails类中。这不是
ActiveSupport::Concern
构建的目的吗?谢谢,但我的想法是,我想将我的模块包含在
ActionDispatch::Routing::UrlFor
中,这样所有包含它的Rails类都会自动获得这些新方法。我不想迭代包含此模块的每个Rails类。如果我有一个所有这些类的列表,我可以简单地将我的模块直接包含到它们中。最终,你想在这里实现什么?你能用一个具体的例子来说明你的用例吗?也许你的问题可以用不同的方法解决。我想在
ActionDispatch::Routing::UrlFor
Rails模块中包含我的模块,这样所有包含它的Rails类都会自动拥有我的新方法。我以不同的方式解决了这个问题,但很惊讶它不能以这种方式工作。
module A

  class<<self
    attr_accessor :observers
  end

  self.observers = []

  def a
    "#{self} successfully called a"
  end

  def self.included(base)
    self.observers << base unless self.observers.include?(base)
  end

  def self.include(mod)
    observers.each {|o| o.send(:include,mod) }
    super
  end

end

module B
  def b
    "#{self} successfully called b"
  end
end

class C
  include A
end

module A
  include B
end

class D
  include A
end

module E
  def e
    "#{self} successfully called e"
  end
end

module A
  include E
end

puts C.new.b 
puts D.new.b 
puts C.new.e
puts D.new.e