How to get all class names in a namespace in Ruby?
RubyRuby Problem Overview
I have a module Foo
, that it is the namespace for many classes like Foo::Bar
, Foo::Baz
and so on.
Is there an way to return all class names namespaced by Foo
?
Ruby Solutions
Solution 1 - Ruby
Foo.constants
returns all constants in Foo
. This includes, but is not limited to, classnames. If you want only class names, you can use
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
If you want class and module names, you can use is_a? Module
instead of is_a? Class
.
Solution 2 - Ruby
If, instead of the names of the constants, you want the classes themselves, you could do it like this:
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
Solution 3 - Ruby
In short no. However, you can show all classes that have been loaded. So first you have to load all classfiles in the namespace:
Dir["#{File.dirname(__FILE__)}/lib/foo/*.rb"].each {|file| load file}
then you can use a method like Jörg W Mittag's to list the classes >Foo.constants.map(&Foo.method(:const_get)).grep(Class)
Solution 4 - Ruby
This will only return the loaded constants under the given namespace because ruby uses a lazy load approach. So, if you type
Foo.constants.select {|c| Foo.const_get(c).is_a? Class}
you will get
[]
but after typing:
Foo::Bar
you will get
[:Bar]
Solution 5 - Ruby
This alternative solution will load and show all classes under Foo::
including "nested" classes, e.g. 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::" }
Note: **/*.rb
recursively globs.
If you want to include the Foo
class itself, you could change your select
to e.g. { |c| c.to_s =~ /^Foo\b/ }