Is there a way to get a collection of all the Mode

2019-01-02 16:30发布

Is there a way that you can get a collection of all of the Models in your Rails app?

Basically, can I do the likes of: -

Models.each do |model|
  puts model.class.name
end

27条回答
人间绝色
2楼-- · 2019-01-02 17:03

For Rails5 models are now subclasses of ApplicationRecord so to get list of all models in your app you do:

ApplicationRecord.descendants.collect { |type| type.name }

Or shorter:

ApplicationRecord.descendants.collect(&:name)

If you are in dev mode, you will need to eager load models before:

Rails.application.eager_load!
查看更多
低头抚发
3楼-- · 2019-01-02 17:03

To avoid pre-load all Rails, you can do this:

Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }

require_dependency(f) is the same that Rails.application.eager_load! uses. This should avoid already required file errors.

Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants

查看更多
姐姐魅力值爆表
4楼-- · 2019-01-02 17:05

This worked for me. Special thanks to all the posts above. This should return a collection of all your models.

models = []

Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
  temp = model_path.split(/\/models\//)
  models.push temp.last.gsub(/\.rb$/, '').camelize.constantize rescue nil
end
查看更多
看淡一切
5楼-- · 2019-01-02 17:08

I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.

Let say you have a column public_uid that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)

Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this

# lib/tasks/data_integirity.rake
namespace :di do
  namespace :public_uids do
    desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
    task generate: :environment do
      Rails.application.eager_load!
      ActiveRecord::Base
        .descendants
        .select {|f| f.attribute_names.include?("public_uid") }
        .each do |m| 
          m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
      end 
    end 
  end 
end

you can now run rake di:public_uids:generate

查看更多
人气声优
6楼-- · 2019-01-02 17:10

If you want just the Class names:

ActiveRecord::Base.descendants.map {|f| puts f}

Just run it in Rails console, nothing more. Good luck!

EDIT: @sj26 is right, you need to run this first before you can call descendants:

Rails.application.eager_load!
查看更多
十年一品温如言
7楼-- · 2019-01-02 17:10

ActiveRecord::Base.connection.tables

查看更多
登录 后发表回答