是否有一种方法可以获得Rails应用程序中所有模型的集合?

基本上,我能做的是:-

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

当前回答

我认为@hnovick的解决方案是一个很酷的,如果你没有表的模型。这个解决方案也可以在开发模式下工作

但我的方法略有不同

ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact

分类应该能从字符串中正确地给出类名。safe_constantise确保您可以安全地将其转换为类,而不会抛出异常。如果您的数据库表不是模型,则需要这样做。紧凑,以便删除枚举中的任何nil。

其他回答

Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }

刚刚看到这个,因为我需要打印所有模型的属性(基于@Aditya Sanghi的评论):

ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "\n\n"+model.name; model.new.attributes.each{|a,b| print "\n#{a}"}}

是的,有很多方法可以找到所有的模型名称,但我在我的gem model_info中所做的是,它会给你所有的模型,甚至包括在gems中。

array=[], @model_array=[]
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
  if  x.split('::').last.split('_').first != "HABTM"
    @model_array.push(x)
  end
  @model_array.delete('ActiveRecord::SchemaMigration')
end

然后打印出来

@model_array

以下是一个经过复杂Rails应用程序(支持Square的应用程序)审查的解决方案

def all_models
  # must eager load all the classes...
  Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
    begin
      require model_path
    rescue
      # ignore
    end
  end
  # simply return them
  ActiveRecord::Base.send(:subclasses)
end

它采用了这篇文章中最好的答案,并将它们组合成最简单、最彻底的解决方案。当你的模型在子目录中时,可以使用set_table_name等。

Rails 3、4和5的完整答案是:

如果cache_classes是关闭的(在开发中默认是关闭的,但在生产中是打开的):

Rails.application.eager_load!

然后:

ActiveRecord::Base.descendants

这将确保加载应用程序中的所有模型,无论它们位于何处,并且也加载了您使用的任何提供模型的gem。

这应该也适用于从ActiveRecord::Base继承的类,如Rails 5中的ApplicationRecord,并只返回后代的子树:

ApplicationRecord.descendants

如果您想了解更多关于这是如何完成的,请查看ActiveSupport:: descent stracker。