16

我有一大堆子类,它们通过我的 Rails 应用程序中的单表继承从父类继承。我想要一种方法来获取从主类继承的所有子类的数组。

我尝试了在另一个 SO 答案中找到的以下单链接命令,但它只返回父类。

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

有什么干净的方法可以做到这一点吗?

编辑: 显然 Rails 在 Dev 模式下调用时只会延迟加载子类,并且可能会根据 Rails 版本进行生产。但是,第一个答案应该在 Prod 模式下适用于 Rails 3.1 及更高版本。

4

7 回答 7

31

ClassRails使用subclasses()方法扩展了 Ruby 。

在 Rails 3 中,您可以直接调用它:

YourClass.subclasses

在 Rails 2.3 中,“.subclasses”是受保护的,所以我们必须使用以下方式调用它send()

YourClass.send(:subclasses)
于 2012-05-10T14:44:45.730 回答
15

您需要预先加载类,如:https ://github.com/rails/rails/issues/3364 中所述

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

然后您将能够使用:

YourClass.subclasses

或者

YourClass.descendants
于 2013-10-04T05:12:01.963 回答
6

在你的config/environments/development.rb

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

你可以将false改为true,然后在你的控制台中做

Class.subclasses

或者

Class. descendants

这是子类后代之间的区别

子类:

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

Foo.subclasses # => [Bar]

后人:

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]
于 2018-07-06T09:01:03.667 回答
5
ParentClass.subclasses.map(&:name)
于 2016-07-26T07:15:26.240 回答
1

这将在一个 SQL 查询中完成:

# SELECT DISTINCT type FROM objects
Object.uniq.pluck(:type)
于 2013-09-26T10:07:27.527 回答
0

请注意,它们是实现上述 Dave G 方法的更有效方法。

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

这首先从数据库发送仅具有“类型”属性的封送对象,这会占用更少的内存,然后仅将类型提取到一个数组中,然后您可以对其进行uniq处理。我确信有一种无限高效的纯 SQL 方法可以做到这一点。

于 2012-07-21T16:02:43.693 回答
-8

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

Object.all.uniq{|x| x.type}.collect(&:type)
于 2012-05-10T14:04:09.450 回答