According to Wikipedia STI is
Single table inheritance is a way to emulate object-oriented inheritance in a relational database. When mapping from a database table to an object in an object-oriented language, a field in the database identifies what class in the hierarchy the object belongs to. In Ruby on Rails the field in the table called ‘type’ identifies the name of the class.
I hope that explains you what STI is, so lets see how can we implement this in our Rails Application. Let’s consider a scenario where we have a user, the user can be multiple types depending on the access rights, like “Owner”, “Admin”, “Guest”.
First Step : Create a class with the name of a specific type(For instance : Owner)
Create a new Ruby class file in your rails app/models directory and give it the name of one of the type/s e.g. Owner.rb

And similarly create classes for Admin and Guest
Second Step : Let these classes extend the User class
class Owner < User end
Third Step : Add a type field to the User Model
This type field will store the type of user. ie. Owner, Admin or Guest. You can add the field as follows:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.string :email
t.string :password
t.string :type
end
def self.down
drop_table :user
end
end
Fourth Step : Add the following code in the User Model
class << self
def new_with_cast(*a,&b)
if (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self
raise "Error!!" unless klass < self # klass should be a descendant of User
return klass.new(h, &b)
end
new_without_cast(*a, &b)
end
alias_method_chain :new, :cast
end
What we do here basically is, we are checking
- Are we getting some value in the type field from the user submitted values
- If we are getting some value we constantize the string and then we check whether the recieved constant is one of the descendant of User class. If not then we raise an Exception.
- If the constant is one of the descendant of User class ['Owner','Admin','Guest'], then the User becomes of that type.
Fifth Step : Changes in new.html.erb and edit.html.erb
In new and edit page of User add a select field which will determine the type of User
<p> <%= f.label :type %><br /> <%= f.select :type, ["Owner", "Admin", "Guest"] %> </p>
Last Step : We have done it. Time to test.
That is it. We have successfully implemented the functionality of Single Table Inheritance. Lets take a look how things go.
User.create(:name => "Rohit", :email => "rohit0981989@gmail.com", :password => "test123456" ,:type => "Owner")
#This line will create a record in User model with type Owner.
@user = User.find_by_name("Rohit")
#This will give an object of type Owner, because we have set the type as Owner.
Everything seems to be working fine.
Thanks for reading the post. any suggestions are most welcome.
Rohit
You appear to be quite experienced in this field. I’m having a problem whereby I can successfullly create the sub classes in new form. However whenever I try to edit. the edit code runs withour error, but the SQL UPDATE call is never made when i check in the logs. have you come across this before ?
Hi Chris,
Thanks for the complement, but even I am still an explorer in the rails world.
Can you post your code somewhere, so that I can take a look?
hi I was fortunate to seek your blog in wordpress
your subject is quality
I learn much in your blog really thanks very much