Как я могу перебрать все Модели в моем приложении rails? - PullRequest
9 голосов
/ 02 мая 2010

Я хотел бы иметь возможность перебирать и проверять все модели в моем приложении rails. В псевдокоде это будет выглядеть примерно так:

rails_env.models.each do |model|  
  associations = model.reflect_on_all_associations(:has_many)  
  ... do some stuff  
end

Мой вопрос: как мне проверить мое приложение rails, чтобы получить коллекцию моделей (rails_env.models)?

Ответы [ 5 ]

13 голосов
/ 24 ноября 2011

Аналогично ответу nathanvda, используйте camelize, а не прописную букву для поддержки файлов моделей с подчеркиванием и используйте String # constantize вместо Kernel.const_get.

Кроме того, если вы храните неактивные модели записей в папке моделей (например, класс поиска для консолидации логики поиска), вам нужно проверить, является ли класс активной моделью записи.

Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|
  klass = File.basename(filename, '.rb').camelize.constantize
  next unless klass.ancestors.include?(ActiveRecord::Base)
  next if klass.abstract_class?
  # do something with klass
end
2 голосов
/ 05 мая 2010

Перебирать все файлы в `$ RAILS_ROOT \ app \ models '?

Например

def find_all_models
  # iterate over all files in folder
  folder = File.join(RAILS_ROOT, "app", "models")      
  Dir[File.join(folder, "*")].each do |filename|
    # remove .rb
    model_name = File.basename(filename).sub(/.rb$/, '').capitalize
    model = Kernel.const_get(model_name)
    # .. do something with your model :)
  end
end

Помогает ли это?

1 голос
/ 03 марта 2017

Если вы смотрите на модели ApplicationRecord только в современном приложении Rails, вы можете просто использовать

ApplicationRecord.descendants

Здесь вы можете взглянуть на это: http://apidock.com/rails/Class/descendants

1 голос
/ 01 марта 2017

Я пытался реализовать вышеупомянутые решения под Rails 5, и они не совсем работали. Вот решение, которое находит все модели, которые начинаются с "page_" (или любого другого префикса; просто укажите это):

def self.page_models(prefix = "page")
    models = []
    folder = File.join(Rails.root, "app", "models")
    Dir[File.join(folder, "*")].each do |filename|
     if filename =~ /models\/#{prefix}/
       klass = File.basename(filename, '.rb').camelize.constantize
       models << klass
     end
    end
    return models
end
1 голос
/ 23 апреля 2014

Rails Admin использует этот код (см. https://github.com/sferik/rails_admin/blob/master/lib/rails_admin/config.rb, метод viable_models):

([Rails.application] + Rails::Engine.subclasses.collect(&:instance)).flat_map do |app|
          (app.paths['app/models'].to_a + app.config.autoload_paths).collect do |load_path|
            Dir.glob(app.root.join(load_path)).collect do |load_dir|
              Dir.glob(load_dir + '/**/*.rb').collect do |filename|
                # app/models/module/class.rb => module/class.rb => module/class => Module::Class
                lchomp(filename, "#{app.root.join(load_dir)}/").chomp('.rb').camelize
              end
            end
          end
        end.flatten.reject { |m| m.starts_with?('Concerns::') }

Преимущество заключается в том, что он загружает модели в связанные двигатели, а не только в текущее приложение.

...