4

I'm looking for a way to list all classes defined inside a module (namespace). Here is similar question regarding the problem: How to get all class names in a namespace in Ruby?

but see the last reply, the Module.constants is empty until the class is called/loaded. Is there any way to do this without manually referencing each class?

I'm trying to use this feature in Rails 3.2, and the only way I found was requiring each class in initializer (didn't try it but it still requires manual typing...).

Thanks in advance for your time.

Community
  • 1
  • 1
rui
  • 115
  • 1
  • 8

3 Answers3

2

You could glob the files in a namespaced directory as such:

Dir.glob('/path/to/namespaced/directory/*').collect{|file_path| File.basename(file_path, '.rb').constantize}

So in a Rails initialization file or model you could do:

Dir.glob(File.join(Rails.root, "app", "models", "my_namespace", "*")).collect{|file_path| File.basename(file_path, '.rb').constantize}
Bryan Liff
  • 439
  • 3
  • 7
  • it's a bitdirty, but I guess it would do the job, so the ansewer accepted, through i decided to keep track of classes in an array. Thank you. – rui Nov 23 '12 at 23:22
2

Building on what Bryan provided, you can use this to get constants/classes from a specific parent namespace, even with filenames/classnames that start/end with some string:

require 'pathname'

# make this the directory you are autoloading from
autoload_dir = File.join(Rails.application.root, 'app', 'models')

# this will return FooBar::BarFoo::**::*Boo constants and autoload them
Dir.glob(File.join(autoload_dir, 'foo_bar', 'bar_foo', '**', '*_boo.rb')).collect{|pathname| Pathname.new(pathname.chomp('.rb')).relative_path_from(Pathname.new(autoload_dir)).to_s.camelize.constantize}
Gary S. Weaver
  • 7,966
  • 4
  • 37
  • 61
2

Bryan Liff's short and elegant answer is almost right, but throws an error. Instead, try:

Dir.glob(File.join(Rails.root, "app", "models", "my_namespace", "*")).collect{|file_path| File.basename(file_path, '.rb').camelize.constantize}

Note the use of camelize. I would have posted this in a comment but don't have sufficient reputation to do so.