Monday, August 23, 2010

Enumerate all Rails ActiveRecord::Base model classes

I couldn't quickly find an easy way to enumerate all ActiveRecord::Base-derived model classes in my Rails project (for some simple analysis scripts), so I whipped up this quick and dirty solution.

I extended ActiveRecord::Base just out of convenience, so I can call ActiveRecord::Base.each_model_class{|klass| ...} easily. You could apply the same technique in another class if you don't like extending Rails core classes.

The "rescue nil" is just a quick hack to catch the cases where you have tables that don't map to classes directly.

NOTE: This does NOT enumerate STI-based model classes that don't have their own tables.


Anonymous said...

Mark and I were looking over this and it occurred to me that Rails already gives you the ability to do this. AR::Base has a protected method `subclasses`.

In a script/console this won't give you all classes if you haven't loaded them into memory (thanks to lazy autoloading), but `ActiveRecord::Base.send :subclasses` will return an array of all models.

The only thing that might differ from yours is that I am not sure if it will return STI classes (i.e. second-level subclasses)

scottwb said...

Nice! Funny, a `subclasses` method was the first thing I tried out of the blue...but I tried it in straight irb, not script/console. Object.subclasses must be added by Rails.

Your solution actually DOES include all the STI classes (and also includes one other subclass in my project that is not mapped to a table), which is probably more "correct".

I'm not sure how the lazy loading would play out for my particular scenario, but on this surface, this way seems like a winner.