Rails single table inheritance (STI)

Kavita Jadhav
2 min readNov 10, 2023


Inheritance is used when entities are of a similar kind but can be categorised further. Child classes represent is_a relationship with parent classes. For example, with parent classes Person and child classes Student, Teacher, and Librarian. We can read it like student is_a person, teacher is_a person etc.


When Inheritance is implemented in Ruby, child classes can inherit parent classes and start using its behaviour. In Rails, models are tightly coupled with databases through ActiveRecord, which requires maintaining the class hierarchy in the database as well as using type columns.

database tables are created along with the model using the rails generate model command. To create the same class hierarchy mentioned above, we need to create models of person, student, teacher, and librarian but only one table having name people in the database.

Create the first model person with the command:

rails g model person first_name:string last_name:string type:string email:string

This will create the Person model and migration file like below:

class Person < ApplicationRecord
class CreatePeople < ActiveRecord::Migration[7.0]
def change
create_table :people do |t|
t.string :first_name
t.string :last_name
t.string :type
t.string :email


Now to create sub-classes student, teacher, and librarian, without database tables run below commands.

rails g model teacher --skip-migration
rails g model librarian --skip-migration
rails g model student --skip-migration
class Teacher < ApplicationRecord

class Librarian < ApplicationRecord

class Student < ApplicationRecord

Now the next step is to update class definitions to extend the Person class like the below:

class Teacher < Person

class Librarian < Person

class Student < Person

We are ready to use these classes and create database records. Create the below records from the rails console.

student = Student.create(first_name: 'Kavita', last_name: 'Jadhav', email: 'kavita@mail.com')
teacher = Teacher.create(first_name: 'Jyoti', last_name: 'Jadhav', email: 'kavita@mail.com')
librarian = Librarian.create(first_name: 'Ravi', last_name: 'Jadhav', email: 'kavita@mail.com')

These will create records in the people table with their respective types. When querying person records with the orm all method, it will list all three records, but then the all method is run with individual child class, it will return list single record of the respective class.


Happy coding!