查找模块中可用的类


75

我有一个模块MyModule。我动态地将类加载到其中。如何获得在其命名空间中定义的类的列表?

例:

def load_plugins
  Dir.glob(File.dirname(__FILE__) + '/plugins/*.rb') do |f|
    MyModule.class_eval File.read(f)
  end

  # now how can I find the new classes I've loaded into MyModule?
end

我应该说每个都f包含类似“ Foo类;结束”的内容。

您也可以这样想:在Rails中,如何以编程方式找到ActiveRecord模块中定义的所有类?

Answers:


128

通过常量访问类。模块中定义的类在该模块中列为常量。因此,您只需要选择引用类的常量即可。

MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}

7
一件事:为什么使用该测试代替“ MyModule.const_get(c).is_a?类”?我不喜欢这样使用“ ===”。
joshuaxls

3
没有令人信服的理由。===版本对我来说更具可读性。使用is_a?也会一样好。
查克(Chuck)

6
避免显式使用大小写相等运算符===。顾名思义,它意在被case表达式隐式使用,并且在表达式之外会产生一些令人困惑的代码。 [样式指南]
James Fernandes

不知道为什么,但这在Ruby内置模块(如Kernel,Comparable和Enumerable)上不起作用。
vishnuprasanth '16

1
@Vizkrig:AFAIK这些模块不应包含任何类。如果你正在寻找的类包括一个模块,而不是类,一个模块,这是一个不同的问题
Chuck

1

如果您在轨道上,则需要先访问常量以使其显示,因为它们是延迟加载的。

MyModule::NotAClass = "not a class"

MyModule.constants => [:NotAClass]

MyModule::AClass => :AClass # Access class for it to be autoloaded

MyModule.constants => [:AClass, :NotAClass]

# Now, select the constants which are class instances

MyModule.constants
        .map(&MyModule.method(:const_get))
        .select { |constant| constant.is_a? Class} 

 => [MyModule::AClass]**
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.