【发布时间】:2010-09-09 11:56:41
【问题描述】:
我有一个模块Foo,它是Foo::Bar、Foo::Baz 等许多类的命名空间。
有没有办法返回以Foo命名的所有类名?
【问题讨论】:
标签: ruby
我有一个模块Foo,它是Foo::Bar、Foo::Baz 等许多类的命名空间。
有没有办法返回以Foo命名的所有类名?
【问题讨论】:
标签: ruby
Foo.constants
返回Foo 中的所有常量。这包括但不限于类名。如果你只想要类名,你可以使用
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
如果你想要类和模块名,你可以使用is_a? Module 而不是is_a? Class。
【讨论】:
Dir["app/models/foo/*.rb"].each {|file| load file}
如果你想要类本身而不是常量的名称,你可以这样做:
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
【讨论】:
Module.constants.select(&Module.method(:const_defined?)).map(&Module.method(:const_get)).grep(Class) 之类的崩溃
简而言之,没有。但是,您可以显示所有已加载的类。 所以首先你必须加载命名空间中的所有类文件:
Dir["#{File.dirname(__FILE__)}/lib/foo/*.rb"].each {|file| load file}
那么您可以使用 Jörg W Mittag 之类的方法来列出类
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
【讨论】:
这只会返回给定命名空间下加载的常量,因为 ruby 使用延迟加载方法。 所以,如果你输入
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
你会得到
[]
但是在输入之后:
Foo::Bar
你会得到
[:Bar]
【讨论】:
此替代解决方案将加载并显示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/ }
【讨论】: