Получить все модели, внедрив определенный метод - PullRequest
1 голос
/ 06 февраля 2010

У меня есть много моделей, созданных с помощью стандартного генератора моделей рельсов. Некоторые модели получили метод foo ().

Есть ли простой способ выяснить все имена классов сгенерированных моделей, в которых реализован метод foo ()?

Я имею в виду программно, с контроллера rails, а не с консоли, извлекающей исходный код.

1 Ответ

2 голосов
/ 06 февраля 2010

Rails не хранит индекс ваших моделей, поэтому вам просто нужно пройтись по каталогу app/models.

Вот пример:

# 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 загружает ваши модели и контроллеры лениво, при первом обращении к ним. Это делается с помощью метода const_missing Руби, и вы можете увидеть всю магию, происходящую в ActiveSupport в active_support/dependencies.rb.

Чтобы немного прояснить, что происходит выше, вам также нужно знать, что имена классов и имена файлов связаны между собой. Rails ожидает, что модель ThingyBob будет жить в thingy_bob.rb. Для преобразования между этими двумя именами используется метод String camelize. (Обратным будет метод underscore.) Эти расширения String также являются частью ActiveSupport.

Наконец, с помощью метода ActiveSupport constantize, который также является расширением String, мы разыменовываем строку как константу. Так что в основном "ThingyBob".constantize - это то же самое, что просто писать ThingyBob; мы просто возвращаем класс ThingyBob. В приведенном выше примере constantize также запускает обычную магию загрузки зависимостей.

Надежда, которая помогает демистифицировать некоторые вещи. :)

...