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

基本上,我能做的是:-

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

当前回答

这对我很管用。特别感谢上面所有的帖子。这将返回所有模型的集合。

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

其他回答

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

模型不会将自己注册到主对象,所以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

这似乎对我很管用:

  Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
  @models = Object.subclasses_of(ActiveRecord::Base)

Rails只在使用模型时加载模型,因此Dir。Glob行“需要”models目录中的所有文件。

一旦你在数组中有了模型,你可以做你想做的事情(例如在视图代码中):

<% @models.each do |v| %>
  <li><%= h v.to_s %></li>
<% end %>

确保在调用后代之前加载你的应用程序,这样所有的类都被加载了:

Rails.application.eager_load! unless Rails.application.config.eager_load

ApplicationRecord.descendants.each do |clazz|
  # do something with clazz, e.g. User, Event, Attendance, etc.
end

这适用于Rails 3.2.18

Rails.application.eager_load!

def all_models
  models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
    m.chomp('.rb').camelize.split("::").last
  end
end

我在Rails 4中尝试了很多这样的答案,但都没有成功(哇,看在上帝的份上,他们改变了一两件事),所以我决定添加我自己的答案。调用ActiveRecord::Base的那些。连接和拉表名工作,但没有得到我想要的结果,因为我隐藏了一些模型(在app/models/内的文件夹中),我不想删除:

def list_models
  Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end

我把它放在初始化式中,可以在任何地方调用它。防止不必要的鼠标使用。