Ruby on Rails Single Table Inheritance Basic example


Example

First we need a table to hold our data

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :password
      t.string :type # <- This makes it an STI

      t.timestamps
    end
  end
end

Then lets create some models

class User < ActiveRecord::Base
   validates_presence_of :password
   # This is a parent class. All shared logic goes here
end

class Admin < User
   # Admins must have more secure passwords than regular users
   # We can add it here
   validates :custom_password_validation
end

class Guest < User
   # Lets say that we have a guest type login. 
   # It has a static password that cannot be changed
   validates_inclusion_of :password, in: ['guest_password']
end

When you do a Guest.create(name: 'Bob') ActiveRecord will translate this to create an entry in the Users table with type: 'Guest'.

When you retrieve the record bob = User.where(name: 'Bob').first the object returned will be an instance of Guest, which can be forcibly treated as a User with bob.becomes(User)

becomes is most useful when dealing with shared partials or routes/controllers of the superclass instead of the subclass.