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?
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?
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.
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)
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)
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]
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/ }