This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Add AR::Base class methods for enumerating all the model | |
# classes in a Rails project. | |
module ActiveRecord | |
class Base | |
def self.all_model_classes | |
connection.tables.map do |table| | |
begin | |
klass = Class.const_get(table.classify) | |
klass.ancestors.include?(self) ? klass : nil | |
rescue | |
nil | |
end | |
end.compact | |
end | |
def self.each_model_class(&block) | |
all_model_classes.each(&block) | |
end | |
end | |
end |
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.
2 comments:
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)
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.
Post a Comment