有没有办法可以在Rails应用程序中获得所有模型的集合?
基本上,我可以这样做: -
Models.each do |model| puts model.class.name end
sj26.. 376
Rails 3,4和5的整个答案是:
如果cache_classes
关闭(默认情况下它在开发中关闭,但在生产中关闭):
Rails.application.eager_load!
然后:
ActiveRecord::Base.descendants
这样可以确保应用程序中的所有模型(无论它们在何处)都已加载,并且还会加载任何提供模型的宝石.
这也适用于继承的类ActiveRecord::Base
,比如ApplicationRecord
在Rails 5中,并且只返回后代的子树:
ApplicationRecord.descendants
如果您想了解更多关于如何做到这一点,检查出的ActiveSupport :: DescendantsTracker.
Rails 3,4和5的整个答案是:
如果cache_classes
关闭(默认情况下它在开发中关闭,但在生产中关闭):
Rails.application.eager_load!
然后:
ActiveRecord::Base.descendants
这样可以确保应用程序中的所有模型(无论它们在何处)都已加载,并且还会加载任何提供模型的宝石.
这也适用于继承的类ActiveRecord::Base
,比如ApplicationRecord
在Rails 5中,并且只返回后代的子树:
ApplicationRecord.descendants
如果您想了解更多关于如何做到这一点,检查出的ActiveSupport :: DescendantsTracker.
万一有人偶然发现这个,我有另一个解决方案,不依赖于读取或扩展Class类......
ActiveRecord::Base.send :subclasses
这将返回一个类数组.所以你可以这样做
ActiveRecord::Base.send(:subclasses).map(&:name)
编辑:看看评论和其他答案.有比这更聪明的答案!或者尝试将此作为社区维基进行改进.
模型不会将自己注册到主对象,所以不,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.classify.constantize.attribute_names
我找了办法做到这一点,最后选择了这种方式:
in the controller: @data_tables = ActiveRecord::Base.connection.tables in the view: <% @data_tables.each do |dt| %>
<%= dt %> <% end %>
来源:http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
对于Rails5模型现在是子类,ApplicationRecord
以便获取您的应用程序中所有模型的列表:
ApplicationRecord.descendants.collect { |type| type.name }
或更短:
ApplicationRecord.descendants.collect(&:name)
如果您处于开发模式,则需要先加载模型:
Rails.application.eager_load!
我认为@hnovick的解决方案很酷,如果你没有无桌面型号.该解决方案也适用于开发模式
我的方法略有不同但是 -
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact
classify很适合从字符串中正确地给出类的名称.safe_constantize确保您可以安全地将其转换为类而不会抛出异常.如果您的数据库表不是模型,则需要这样做.紧凑,以便删除枚举中的任何nils.
如果你只想要类名:
ActiveRecord::Base.descendants.map {|f| puts f}
只需在Rails控制台中运行它,仅此而已.祝好运!
编辑:@ sj26是对的,你需要先运行它才能调用后代:
Rails.application.eager_load!
这似乎对我有用:
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| %>
在一行: Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
只需一行:
ActiveRecord::Base.subclasses.map(&:name)
我还不能评论,但我认为sj26答案应该是最佳答案.只是一个提示:
Rails.application.eager_load! unless Rails.configuration.cache_classes ActiveRecord::Base.descendants
是的,有很多方法可以找到所有模型名称,但是我在gem model_info中所做的是,它将为您提供甚至包括在gem中的所有模型。
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