Multi-level Single Table Inheritance (STI) in Rails

This took me more than one attempt to get right, so I thought I'd blat it out in a blog post in case anyone else has been struggling with it. In the end, the implementation matches your intuition, but getting the sub-classing syntax right took a few tries (undoubtedly due to my relative newness to Rails/Ruby).

Why would you want multi-level STI? When you're using multiple inheritance (class_c inherits from class_b and class_b inherits from class_a) and you want that relationship maintained through ActiveRecord; that's when.

Take the following three classes for example:


/app/model/a/class_a.rb
class A
def method_a
  "a"
end
end

/app/model/a/class_b.rb (yes, I mean dir 'a'. class_b.rb is a peer of class_a.rb)
class A::B < A
 def method_b
   "b"
 end
end

class A::B::C < A::B
 def method_c
   "c"
 end
end

Notice the explicit class hierarchy notation. Without this, I can't get the multi-level relationship maintained through STI.

From here, you can merrily create the class through ActiveRecord, assuming you have an existing table for the base class (which includes the 'type' column (where AR stashes the class hierarchy/name information for subsequent instanciations), and use all the methods.


A::B::C.create!
...
c = A.first
c.method_a => 'a'
c.method_b => 'b'
c.method_c => 'c'

Jud Valeski

Jud Valeski

Parent, photographer, mountain biker, runner, investor, wagyu & sushi eater, and a Boulderite. Full bio here: https://valeski.org/jud-valeski-bio
Boulder, CO