将现有类添加到模块中

我在app / classes文件夹中有一些现有的ruby类:

class A ... end class B ... end 

我想在模块MyModule中对这些类进行分组

我知道我可以这样做:

 module MyModule class A ... end class B ... end end 

但是有一个元编程快捷方式可以做同样的事情,所以我可以“导入”所有现有的类?

谢谢,吕克

使用const_missing钩子。 如果在当前模块中找不到常量,请尝试在全局命名空间中解析:

 class A; end class B; end module M def self.const_missing(c) Object.const_get(c) end end M::A.new M::B.new 
 module Foo A = ::A B = ::B end Foo::A.new.bar 

请注意,常量上的::前缀首先开始搜索全局命名空间。 像领导/在路径名上。 这允许您将全局类A与模块化常量Foo::A分开来。

@ Squeegy的答案已经告诉你该做什么,但我认为理解为什么这样做同样重要。 它实际上非常简单:Ruby中的类并不特别。 它们就像任何其他对象一样被赋予变量,就像任何其他变量一样。 更确切地说:它们是Class类的实例,它们通常被赋值为常量(即名称以大写字母开头的变量)。

所以,就像你可以将任何其他对象别名为多个变量:

 a = '' b = a a << 'Hello' c = b b << ', World!' puts c # => Hello, World! 

您还可以将类别名替换为多个变量:

 class Foo; end bar = Foo p bar.new # => # 

如果你想移动到命名空间而不是仅仅别名它们,你还需要将原始变量设置为其他对象,如nil ,以及@ Squeegy的答案:

 ::A = nil ::B = nil 

是的,在您的模块中创建类并让它inheritance自您的外部类。 例如,

 class A ... end module MyModule class NewA < A end end 

MyModule :: NewA类将具有A类的所有属性和方法。
然后,ruby中的模块永远不会被锁定,所以没有什么能阻止你直接将类定义写入模块。

如果你想将它们放在一个模块中,我没有看到首先将它们包含在全局命名空间中,然后将它们置于模块中。 我想你想做什么(虽然我怀疑它是一件好事)是这样的:

文件classes/g1.rb

 class A1 def self.a "a1" end end class B1 def self.b "b1" end end 

文件classes/g2.rb

 class A2 def self.a "a2" end end class B2 def self.b "b2" end end 

文件imp.rb

 module MyModule ["g1.rb", "g2.rb"].each do |file| self.class_eval open("classes/#{file}"){ |f| f.read } end end puts defined? MyModule puts defined? A1 puts defined? MyModule::A1 puts MyModule::A1.a puts MyModule::B2.b 

输出

 constant nil constant a1 b2 

我可以想到这种方法的一些缺点(更难以调试一件事,加载可能有点慢,尽管我只是猜测)。

你为什么不这样做:

 Dir["classes/*.rb"].each do |file| contents = open(file) { |f| f.read } open(file, "w") do |f| f.puts "module MyModule\n" contents.each { |line| f.write " #{line}" } f.puts "\nend" end end 

这将修复您的类在您的模块中,因为在ruby中您可以随时重新打开模块。 然后就像你通常那样包括它们。