是否有一种方法可以获得Rails应用程序中所有模型的集合?
基本上,我能做的是:-
Models.each do |model|
puts model.class.name
end
是否有一种方法可以获得Rails应用程序中所有模型的集合?
基本上,我能做的是:-
Models.each do |model|
puts model.class.name
end
当前回答
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
其他回答
万一有人无意中发现了这个问题,我有另一个解决方案,不依赖于dir读取或扩展Class类……
ActiveRecord::Base.send :subclasses
这将返回一个类数组。所以你可以这样做
ActiveRecord::Base.send(:subclasses).map(&:name)
确保在调用后代之前加载你的应用程序,这样所有的类都被加载了:
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
我认为@hnovick的解决方案是一个很酷的,如果你没有表的模型。这个解决方案也可以在开发模式下工作
但我的方法略有不同
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact
分类应该能从字符串中正确地给出类名。safe_constantise确保您可以安全地将其转换为类,而不会抛出异常。如果您的数据库表不是模型,则需要这样做。紧凑,以便删除枚举中的任何nil。
如果你只需要类名:
ActiveRecord::Base.descendants.map {|f| puts f}
只需在Rails控制台中运行它,仅此而已。好运!
编辑:@sj26是正确的,你需要在调用后代之前先运行这个:
Rails.application.eager_load!
如果有人觉得这个例子有用,我就随便举个例子。解决方案是基于这个答案https://stackoverflow.com/a/10712838/473040。
假设您有一个列public_uid,它被用作外部世界的主ID(您可以在这里找到为什么要这样做的原因)
现在假设您已经在一些现有的model上引入了这个字段,现在您想要重新生成所有尚未设置的记录。你可以这样做
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
现在可以运行rake di:public_uid:generate