Ruby-on-rails 有没有办法在你的 Rails 应用程序中获取所有模型的集合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/516579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to get a collection of all the Models in your Rails app?
提问by mr_urf
Is there a way that you can get a collection of all of the Models in your Rails app?
有没有办法可以在 Rails 应用程序中获取所有模型的集合?
Basically, can I do the likes of: -
基本上,我可以做以下事情:-
Models.each do |model|
puts model.class.name
end
采纳答案by Vincent Robert
EDIT: Look at the comments and other answers. There are smarter answers than this one! Or try to improve this one as community wiki.
编辑:查看评论和其他答案。还有比这个更聪明的答案!或者尝试将其作为社区维基来改进。
Models do not register themselves to a master object, so no, Rails does not have the list of models.
模型不会将自己注册到主对象,所以不,Rails 没有模型列表。
But you could still look in the content of the models directory of your application...
但是您仍然可以查看应用程序模型目录的内容...
Dir.foreach("#{RAILS_ROOT}/app/models") do |model_path|
# ...
end
EDIT: Another (wild) idea would be to use Ruby reflection to search for every classes that extends ActiveRecord::Base. Don't know how you can list all the classes though...
编辑:另一个(疯狂的)想法是使用 Ruby 反射来搜索扩展 ActiveRecord::Base 的每个类。不知道如何列出所有课程...
EDIT: Just for fun, I found a way to list all classes
编辑:只是为了好玩,我找到了一种列出所有类的方法
Module.constants.select { |c| (eval c).is_a? Class }
EDIT: Finally succeeded in listing all models without looking at directories
编辑:终于成功列出了所有模型而无需查看目录
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
If you want to handle derived class too, then you will need to test the whole superclass chain. I did it by adding a method to the Class class:
如果您也想处理派生类,则需要测试整个超类链。我通过向 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
回答by sj26
The whole answer for Rails 3, 4 and 5 is:
Rails 3、4 和 5 的完整答案是:
If cache_classesis off (by default it's off in development, but on in production):
如果cache_classes关闭(默认情况下它在开发中关闭,但在生产中打开):
Rails.application.eager_load!
Then:
然后:
ActiveRecord::Base.descendants
This makes sure all models in your application, regardless of where they are, are loaded, and any gems you are using which provide models are also loaded.
这可以确保您的应用程序中的所有模型(无论它们位于何处)都被加载,并且您正在使用的任何提供模型的 gem 也被加载。
This should also work on classes that inherit from ActiveRecord::Base, like ApplicationRecordin Rails 5, and return only that subtree of descendants:
这也应该适用于从 继承的类ActiveRecord::Base,就像ApplicationRecord在 Rails 5 中一样,并且只返回子树的子树:
ApplicationRecord.descendants
If you'd like to know more about howthis is done, check out ActiveSupport::DescendantsTracker.
如果您想了解更多关于这是如何完成的,请查看ActiveSupport::DescendantsTracker。
回答by kikito
Just in case anyone stumbles on this one, I've got another solution, not relying on dir reading or extending the Class class...
以防万一有人偶然发现这个,我有另一个解决方案,不依赖于 dir 读取或扩展 Class 类......
ActiveRecord::Base.send :subclasses
This will return an array of classes. So you can then do
这将返回一个类数组。所以你可以这样做
ActiveRecord::Base.send(:subclasses).map(&:name)
回答by lightyrs
ActiveRecord::Base.connection.tables.map do |model|
model.capitalize.singularize.camelize
end
will return
将返回
["Article", "MenuItem", "Post", "ZebraStripePerson"]
Additional informationIf you want to call a method on the object name without model:string unknown method or variable errors use this
附加信息如果您想在没有模型的情况下调用对象名称上的方法:字符串未知方法或变量错误,请使用此
model.classify.constantize.attribute_names
回答by jaime
I looked for ways to do this and ended up choosing this way:
我寻找方法来做到这一点,最终选择了这种方式:
in the controller:
@data_tables = ActiveRecord::Base.connection.tables
in the view:
<% @data_tables.each do |dt| %>
<br>
<%= dt %>
<% end %>
<br>
source: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
来源:http: //portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
回答by Nimir
For Rails5models are now subclassesof ApplicationRecordso to get list of all models in your app you do:
对于Rails5模型现在是ApplicationRecordso 的子类,要获取应用程序中所有模型的列表,您可以执行以下操作:
ApplicationRecord.descendants.collect { |type| type.name }
Or shorter:
或更短:
ApplicationRecord.descendants.collect(&:name)
If you are in dev mode, you will need to eager load models before:
如果您处于开发模式,则需要在之前预先加载模型:
Rails.application.eager_load!
回答by Aditya Sanghi
I think @hnovick's solution is a cool one if you dont have table-less models. This solution would work in development mode as well
如果您没有无表模型,我认为@hnovick 的解决方案是一个很酷的解决方案。此解决方案也适用于开发模式
My approach is subtly different though -
不过,我的方法略有不同-
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact
classify is well supposed to give you the name of the class from a string properly. safe_constantize ensures that you can turn it into a class safely without throwing an exception. This is needed in case you have database tables which are not models. compact so that any nils in the enumeration are removed.
分类应该正确地从字符串中为您提供类的名称。safe_constantize 确保您可以安全地将其转换为类而不会引发异常。如果您的数据库表不是模型,则需要这样做。紧凑以便删除枚举中的任何 nil。
回答by Jordan Michael Rushing
If you want just the Class names:
如果你只想要类名:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
只需在 Rails 控制台中运行它,仅此而已。祝你好运!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
编辑:@sj26 是对的,您需要先运行它,然后才能调用后代:
Rails.application.eager_load!
回答by bhousel
This seems to work for me:
这似乎对我有用:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Rails 仅在使用时加载模型,因此 Dir.glob 行“需要”模型目录中的所有文件。
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
一旦您将模型放入数组中,您就可以按照您的想法进行操作(例如在视图代码中):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
回答by vjt
On one line: Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
在一行上: Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }

