是否有一种方法可以获得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。

其他回答

假设所有模型都在app/models中,并且你的服务器上有grep和awk(大多数情况下),

# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("\n")

它比Rails.application.eager_load快!或者用Dir遍历每个文件。

编辑:

这种方法的缺点是它忽略了间接继承自ActiveRecord的模型(例如FictionalBook < Book)。最可靠的方法是Rails.application.eager_load!;ActiveRecord::Base.descendants.map(&:name),尽管它有点慢。

Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
  next unless model_path.match(/.rb$/)
  model_class = model_path.gsub(/.rb$/, '').classify.constantize
  puts model_class
end

这将为您提供项目上的所有模型类。

在Rails 6中,Zetiwerk成为默认的代码加载器。

对于快速加载,请尝试:

Zeitwerk::Loader.eager_load_all

Then

ApplicationRecord.descendants

编辑:看看评论和其他答案。有比这个更聪明的答案!或者尝试改进这个社区维基。

模型不会将自己注册到主对象,所以Rails没有模型列表。

但是您仍然可以在应用程序的models目录的内容中查找…

Dir.foreach("#{RAILS_ROOT}/app/models") do |model_path|
  # ...
end

编辑:另一个(疯狂的)想法是使用Ruby反射来搜索每个扩展ActiveRecord::Base的类。我不知道你怎么列出所有的类…

编辑:只是为了好玩,我找到了一种列出所有职业的方法

Module.constants.select { |c| (eval c).is_a? Class }

编辑:终于成功地列出所有型号,而不查看目录

Module.constants.select do |constant_name|
  constant = eval constant_name
  if not constant.nil? and constant.is_a? Class and constant.superclass == ActiveRecord::Base
    constant
  end
end

如果你也想处理派生类,那么你需要测试整个超类链。我通过在Class类中添加一个方法来做到这一点:

class Class
  def extend?(klass)
    not superclass.nil? and ( superclass == klass or superclass.extend? klass )
  end
end

def models 
  Module.constants.select do |constant_name|
    constant = eval constant_name
    if not constant.nil? and constant.is_a? Class and constant.extend? ActiveRecord::Base
    constant
    end
  end
end

是的,有很多方法可以找到所有的模型名称,但我在我的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