There is often a debate with respect to when and how best to implement Single Table Inheritance. We will call it STI. There is also another argument between using Polymorphic Association and Single Table Inheritance. That is however beyond the scope of this article. So we will focus mainly on Implementing Single Table Inheritance.

What is Single Table Inheritance (STI)

This is a design pattern where a super class is inherited by a subclass (many subclasses can exist). For instance, when an edutech application has a User model, it can be inherited by lecturer and student models, where lecturer and student are different types of users.

Let’s get started with the STI implementation of the day.

Creating a Rails Application

We will create an application that has User, Lecturer and Student models. Let’s call it edutech. Go to your project directory via the terminal and run the command below to create a new rails application.

Run rails new edutech -d postgresql

The above command will create a rails application called edutech with postgresql as the database of choice.

Let’s create the user model with email and password. But before we create the user model, add the line below to your Gemfile to ensure the passwords are encrypted.

gem 'bcrypt'

After that, run bundle install to install the bcrypt gem.

Run the next command to create a User model.

rails generate model user email:string password_digest type:string

This creates the user resource which the other classes will inherit from. The password_digest is used because of the bcrypt gem. The type column tells ActiveRecord that the user model will have subclasses, and as such when a user is created, the type attribute is added with respect to the type of user. It could be a lecturer or a student in our case.

Run migration rails db:migrate.

Add has_secure_password to support bcrypt in the User model. After adding basic validations for email and password, the user model looks like this:

user.rb

# user.rb
class User < ApplicationRecord
  has_secure_password

  validates :email, presence: true
  validates :passwordl, presence: true
end

Let’s create the other two models, Lecturer and Student. The diagram below depicts what we are trying to achieve.

single-table-inheritance

The three models should contain the code below but first we create files named lecturer.rb and student.rb in the model folder respectively.

Create two more files in the model folder and name them lecturer.rb and student.rb respectively. Copy the code below to their respective files.

lecturer.rb

# lecturer.rb
class Lecturer < User
  validates :lecturer_code, presence: true
  validates :appointment_date, presence: true
end

students.rb

# student.rb
class Student < User
  validates :student_code, presence: true
  validates :level, presence: true
end

From the classes above, we can see that the Lecturer and Student models inherit from the User model. Thus, they are subclasses of the User model.

If we create a new student, Student.create(student_params), the user table is updated with the new object and the Type column is set to Student.

This brings us to the end of our article on Single Table Inheritance(STI).