views:

25

answers:

1

I have many models created with the standard rails model generator. Some of the models have then got a method called foo().

Is there a simple way to figure out all the class names of the generated models having the foo() method implemented ?

I mean programmaticaly, from a rails controller, not from the console grepping the sourcecode.

+2  A: 

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. :)

Shtééf
Thanks, now everything is clear :)
astropanic