我有一个模块Foo
,它是许多类的命名空间,例如Foo::Bar
,Foo::Baz
等等。
有没有办法返回Foo
命名空间的所有类名?
答案 0 :(得分:54)
Foo.constants
返回Foo
中的所有常量。这包括但不限于类名。如果只想要类名,可以使用
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
如果您需要类和模块名称,可以使用is_a? Module
代替is_a? Class
。
答案 1 :(得分:32)
如果你想要这些类本身,而不是常量的名称,你可以这样做:
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
答案 2 :(得分:12)
这将仅返回给定命名空间下的已加载常量,因为ruby使用延迟加载方法。 所以,如果你输入
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
你会得到
[]
但输入后:
Foo::Bar
你会得到
[:Bar]
答案 3 :(得分:11)
总之没有。但是,您可以显示已加载的所有类。 首先,您必须在命名空间中加载所有类文件:
Dir["#{File.dirname(__FILE__)}/lib/foo/*.rb"].each {|file| load file}
然后您可以使用像JörgWMittag这样的方法来列出类
Foo.constants.map(安培; Foo.method(:const_get))。grep的(类)
答案 4 :(得分:0)
此替代解决方案将加载并显示 Foo::
下的所有类,包括“嵌套”类,例如Foo::Bar::Bar
。
Dir["#{File.dirname(__FILE__)}/lib/foo/**/*.rb"].each { |file| load file }
ObjectSpace.each_object(Class).select { |c| c.to_s.start_with? "Foo::" }
注意:**/*.rb
递归全局。
如果您想包含 Foo
类本身,您可以将 select
更改为例如{ |c| c.to_s =~ /^Foo\b/ }