'Rails STI query all subclasses using base class

Imagine I have this STI table called living things with these such subclasses:

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

I am trying to get a very simple query of all records that INHERIT from subclass "Animal". So I want records wher type= "Cat" or type= "Dog". I don't know why I can't seem to figure this out.

none of these options work:

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

currently 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">]> 


Solution 1:[1]

You can do this:

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

or:

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

This should give you all the records of classes that are subclassed from the Animal class.

Solution 2:[2]

As of rails 4.2 (maybe even before), doing:

Animal.all will automatically render an sql call something like:

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

So there you have it. :-)

Solution 3:[3]

In case you are landing on this question and you're running and your ParentClass.all is not returning all of the subclass records... In Rails 6.0, the query not automatically return all subclasses.

You'll need to add the following in the parent class and specify each subclass that you would like to support:

require_dependency 'subclass_name'

See https://guides.rubyonrails.org/v6.0/autoloading_and_reloading_constants_classic_mode.html#autoloading-and-sti for more details

For Rails 7, a slightly different approach is recommended here: https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#single-table-inheritance

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Niels Kristian
Solution 3 Ben Yee