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

基本上,我能做的是:-

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

当前回答

可以检查一下

@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}

其他回答

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

模型不会将自己注册到主对象,所以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
ActiveRecord::Base.connection.tables.map do |model|
  model.capitalize.singularize.camelize
end

将返回

["Article", "MenuItem", "Post", "ZebraStripePerson"]

附加信息如果你想在对象名上调用一个没有model:string未知方法或变量错误的方法,使用这个

model.classify.constantize.attribute_names

一行:Dir['app/models/\*.rb']。map {|f|文件。basename .camelize (f,“。*”)。constantize}

我还不能评论,但我认为sj26的答案应该是首要答案。提示一下:

Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
def load_models_in_development
  if Rails.env == "development"
    load_models_for(Rails.root)
    Rails.application.railties.engines.each do |r|
      load_models_for(r.root)
    end
  end
end

def load_models_for(root)
  Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
    begin
      require model_path
    rescue
      # ignore
    end
  end
end