Rails STI 使用基础 class 查询所有子 classes

Rails STI query all subclasses using base class

想象一下,我有一个名为生物的 STI table,具有这些子类:

class LivingThing < ActiveRecord::Base
end

class Animal < LivingThing
end

class Plant < LivingThing
end

class Fungus < LivingThing
end

class Cat < Animal
end

class Dog < Animal
end

我正在尝试对从子类 "Animal" 继承的所有记录进行非常简单的查询。 所以我想要类型= "Cat" 或类型= "Dog" 的记录。我不知道为什么我似乎无法弄清楚。

none 这些选项有效:

- animals = LivingThing.all.map{|r| r.kind_of?("Animal")}
- animals = LivingThing.all.map{|r| r.type == "Animal"}
- animals = LivingThing.kind_of?("Animal")

目前LivingThing.all =

 => #<ActiveRecord::Relation [#<Cat id: 2,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Dog id: 3,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">,#<Cat id: 4,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Cat id: 5,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Rose id: 6,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Oak id: 7,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Mushroom id: 6,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">, #<Ringworm id: 8,  status: 1,  created_at: "2016-03-25 00:57:20", updated_at: "2016-03-25 00:57:20">]> 

你可以这样做:

animals = LivingThing.all.map { |r| r if r.class.superclass.name == 'Animal' }

或:

animals = LivingThing.all.map { |r| r if r.class.superclass == Animal }

这应该会为您提供从 Animal class.[=12 子class编辑的 classes 的所有记录=]

从 rails 4.2(甚至更早)开始,正在做:

Animal.all 将自动呈现一个 sql 调用,例如:

SELECT * FROM "living_things" WHERE "living_things"."type" IN ('Animal', 'Dog', 'Cat')

好了。 :-)

如果您正着手解决这个问题,并且您 运行 而您的 ParentClass.all 没有 return 所有子 class 记录...在 Rails 6.0 中,查询不会自动 return all subclasses.

您需要在父 class 中添加以下内容并指定您想要支持的每个子class:

require_dependency 'subclass_name'

有关详细信息,请参阅 https://guides.rubyonrails.org/v6.0/autoloading_and_reloading_constants_classic_mode.html#autoloading-and-sti

对于Rails7,这里推荐一种稍微不同的方法:https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#single-table-inheritance