Andy from Webcrunch

Subscribe for email updates:

Portrait of Andy Leverenz
Andy Leverenz

May 1, 2024

Last updated May 2, 2024

Simplifying Data with Rails Single Table Inheritance

When you build apps with Ruby on Rails, managing a lot of data can be tricky, especially when different parts of your app are similar but not the same.

Rails has a cool feature called Single Table Inheritance (STI) that helps with this. This post explores how to use Rails' single table inheritance, why it's helpful, and other options you might consider if you’re not the biggest fan.

What is Rails Single Table Inheritance?

STI Illustration using Furniture as an example

Rails single table inheritance (STI) allows different parts of your app to share the same table in the database. This makes it easier to handle your data because everything is in one place but can still act differently.

How to Set Up Rails Single Table Inheritance

Setting up STI in Rails means making one primary model and a table with a special column called type. This column helps Rails figure out what kind of data is being stored. Here’s how you can do it:

Step 1: Create the Main Table

You need to make a table that holds all the data that your parts of the app will share. We’ll use a Vehicle table as the main table in this example.

# Migration to create a vehicles table with STI support
class CreateVehicles < ActiveRecord::Migration[6.1]
  def change
    create_table :vehicles do |t|
      t.string :type
      t.string :make
      t.string :model
      t.integer :year
      t.timestamps
    end
  end
end

Step 2: Make Models for Each Part

You create a primary model called Vehicle and other models like Car and Truck that will act as the specific parts.

# app/models/vehicle.rb
class Vehicle < ApplicationRecord
end

# app/models/car.rb
class Car < Vehicle
end

# app/models/truck.rb
class Truck < Vehicle
end

With Rails STI, you can make and use cars or trucks easily, and Rails keeps track of what type they are when they are made based on the type column.

Step 3: Using the Models

Just like any other part of your app, you can make new cars or find all trucks easily.

# Creating a new car
Car.create(make: 'Toyota', model: 'Corolla', year: 2021)

# Looking at all cars
Car.all

Querying for data

Now, we have more flexibility when it comes to queries. Say you want to query for all Trucks. There are a couple of approaches.

trucks = Vehicle.where(type: 'truck')

trucks_alt = Truck.all

When Should You Use Rails Single Table Inheritance?

It’s a good idea to use Rails STI when:

  • Different parts of your app are almost the same.
  • These parts share many features.
  • You want to make finding and working with data simpler.

An example here might be an Entry parent class that can be a Message or Comment. The Message and Comment class inherit from Entry, thus creating a shared role where it makes sense.

Other Options Besides Rails Single Table Inheritance

Rails STI is great, but sometimes, it might make your table too big or mix up data. Here are some other ways to handle this:

Polymorphic Associations:

This lets parts of your app connect with many different models.

Using Gems for Table Inheritance:

Some tools, like the acts_as_tenant gem, help keep things orderly, primarily if your app serves many users at once.

Multiple Table Inheritance:

This means making a separate table for each part but keeping the shared data lined up through extra code or database tricks.

Wrapping up

Rails single table inheritance is a handy tool for keeping your app's data neat and making your life easier when working with similar data. But remember, it's essential to choose the method that fits what your app needs the most. Pick the one that makes your app work best, whether it's STI or another technique. My best advice is to not force STI for the sake of using STI but instead if the exact setup makes sense for it. You don’t want to back into any corners you can’t escape.

Link this article
Est. reading time: 3 minutes
Stats: 147 views

Categories

Collection

Part of the Ruby on Rails collection