Rails doesn't keep an index of your models, so you'll simply have to walk your app/models
directory.
Here's an example:
# Open the model directory
models_dir = Dir.open("#{RAILS_ROOT}/app/models")
# Walk directory entries
models = models_dir.collect do |filename|
# Get the name without extension.
# (And skip anything that isn't a Ruby file.)
next if not filename =~ /^(.+)\.rb$/
basename = $~[1]
# Now, get the model class
klass = basename.camelize.constantize
# And return it, if it implements our method
klass if klass.method_defined? :foo
end
# Remove nils
models.compact!
Rails loads your models and controllers lazily, the first time they are referenced. This is done using Ruby's const_missing
method, and you can see all the magic happening in ActiveSupport in active_support/dependencies.rb
.
To elaborate a bit one what's happening above, you also need to know that class names and filenames are linked. Rails expects a ThingyBob
model to live in thingy_bob.rb
. The way to convert between those two names is using the String method camelize
. (The reverse would be the underscore
method.) These String extensions are also part of ActiveSupport.
Finally, with the ActiveSupport method constantize
, which is also a String extension, we dereference a string as a constant. So basically "ThingyBob".constantize
is the same as just writing ThingyBob
; we simply get the ThingyBob
class back. In the example above,constantize
triggers the regular dependency loading magic too.
Hope that helps demystify some things. :)