简体   繁体   English

从Rails中的单表继承获取子类的列表/数组?

[英]Get a list/array of child classes from Single Table Inheritance in Rails?

I have a whole bunch of child classes that inherit from a parent class via single-table-inheritance in my Rails app. 我有一大堆子类,通过我的Rails应用程序中的单表继承从父类继承。 I'd like a way to get an array of all the child classes that inherit from the main class. 我想要一种方法来获取从主类继承的所有子类的数组。

I tried the following single-link command that I found in another SO answer, but it only returns the parent class. 我尝试了在另一个SO答案中找到的以下单链接命令,但它只返回父类。

ObjectSpace.each_object(class<<MyParentClass;self;end)

Is there any clean way to do this? 有没有干净的方法来做到这一点?

EDIT: Apparently Rails only lazy-loads child classes when called in Dev mode, and possibly production depending on the Rails version. 编辑:显然Rails只在惰性模式下调用延迟加载子类,并且可能根据Rails版本生成。 However, the first answer should work on Rails 3.1 and higher in Prod mode. 但是,第一个答案应该适用于Prod模式下的Rails 3.1及更高版本。

Rails extends Ruby Class with the subclasses() method. Rails使用subclasses()方法扩展Ruby Class

In Rails 3 you can call it directly: 在Rails 3中,您可以直接调用它:

YourClass.subclasses

In Rails 2.3, ".subclasses" is protected, so we use have to call it using send() : 在Rails 2.3中,“。subclasses”受到保护,因此我们必须使用send()来调用它:

YourClass.send(:subclasses)

You need to eager load the classes, as stated in: https://github.com/rails/rails/issues/3364 您需要急切加载类,如下所述: https//github.com/rails/rails/issues/3364

ActionDispatch::Reloader.to_prepare do
  Rails.application.eager_load!
end

Then you will be able to use: 然后你就可以使用:

YourClass.subclasses

or 要么

YourClass.descendants
ParentClass.subclasses.map(&:name)

In your config/environments/development.rb config / environments / development.rb中

Rails.application.configure do
  config.eager_load = false
end

U can change false to true , and then in your console to do 你可以将false改为true ,然后在你的控制台中做

Class.subclasses

or 要么

Class. descendants

here is the difference between subclasses and descendants 这是子类后代之间的区别

subclasses: 子类:

class Foo; end
class Bar < Foo; end
class Baz < Bar; end

Foo.subclasses # => [Bar]

descendants: 子孙:

class C; end
C.descendants # => []

class B < C; end
C.descendants # => [B]

class A < B; end
C.descendants # => [B, A]

class D < C; end
C.descendants # => [B, A, D]

This will do it in one SQL query: 这将在一个SQL查询中执行:

# SELECT DISTINCT type FROM objects
Object.uniq.pluck(:type)

Note, their is a more efficient way to implement Dave G's method above.. 注意,它们是实现上述Dave G方法的更有效方法。

Object.select(:type).map(&:type).uniq

This first sends marshaled objects that only have the "type" attribute from the DB, which takes WAY less memory, then plucks only the types into an array that you can then uniq on. 这首先发送只有来自数据库的“type”属性的封送对象,这会占用更少的内存,然后只将类型提取到一个数组中,然后可以单独使用。 I'm sure there is an infinitely more efficient pure SQL way to do this though. 我确信有一种无限高效的纯SQL方法可以做到这一点。

假设表中至少有一个对象存在:

Object.all.uniq{|x| x.type}.collect(&:type)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM