是否有一种方法可以获得Rails应用程序中所有模型的集合?
基本上,我能做的是:-
Models.each do |model|
puts model.class.name
end
是否有一种方法可以获得Rails应用程序中所有模型的集合?
基本上,我能做的是:-
Models.each do |model|
puts model.class.name
end
当前回答
如果有人觉得这个例子有用,我就随便举个例子。解决方案是基于这个答案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
其他回答
在Rails 6中,Zetiwerk成为默认的代码加载器。
对于快速加载,请尝试:
Zeitwerk::Loader.eager_load_all
Then
ApplicationRecord.descendants
Rails 3、4和5的完整答案是:
如果cache_classes是关闭的(在开发中默认是关闭的,但在生产中是打开的):
Rails.application.eager_load!
然后:
ActiveRecord::Base.descendants
这将确保加载应用程序中的所有模型,无论它们位于何处,并且也加载了您使用的任何提供模型的gem。
这应该也适用于从ActiveRecord::Base继承的类,如Rails 5中的ApplicationRecord,并只返回后代的子树:
ApplicationRecord.descendants
如果您想了解更多关于这是如何完成的,请查看ActiveSupport:: descent stracker。
万一有人无意中发现了这个问题,我有另一个解决方案,不依赖于dir读取或扩展Class类……
ActiveRecord::Base.send :subclasses
这将返回一个类数组。所以你可以这样做
ActiveRecord::Base.send(:subclasses).map(&:name)
一行:Dir['app/models/\*.rb']。map {|f|文件。basename .camelize (f,“。*”)。constantize}
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }