Rails Single Table Inheritance

Ruby on Rails supports Single Table Inheritance. Single Table Inheritance allows you to have one single SQL table, such as an employees table, manage different type of employees like managers and developers. A manager would normally have more responsibilities than a developer and you can separate these additional responsibilities in a different ActiveRecord model class.

Here is another example of Single Table Inheritance that you might find useful. You might have to support a hierarchy of users for you web application, such as User, Editor, and Administrator. An Administrator might have full Create, Read, Update, and Delete (CRUD) access while a User might just have read access. For this hierarchy of users you will need to create a Ruby class for each type and place it in the Rails app/models directory. Here is the base User class:

class User < ActiveRecord::Base
end

My Editor class:

class Editor < User
end

And the Administrator class:

class Administrator < Editor
end

Place each of these classes in their own Rails model file under the app/models directory.

To indicate to Ruby on Rails that the users table needs to support Single Table Inheritance you need to add a column named ‘type’ to the users table. Here is my users table definition:

CREATE TABLE users (
   id INT NOT NULL AUTO_INCREMENT,
   user VARCHAR(15) NOT NULL UNIQUE,
   pass VARCHAR(40) NOT NULL,
   type VARCHAR(20) NOT NULL,
   PRIMARY KEY (id)
);

In the column named type you should store the name of the class, the class type, that should be used for each user. To mark an certain user as an admin set his type to ‘Administrator’. By setting a user’s type to ‘Administrator’ you are giving him full administrator privileges as defined in your Administrator model class.

And now, in your controller you can look up all users that are administrators by using the following bit of code:

allAdmins = Administrator.find(:all)

If you want to look up all known users you can do so by using the User class as in the following snippet of code:

allUsers = User.find(:all);

At this point, you would add additional responsibilities to editors and administrators by adding methods to those model classes.

Related posts:

  1. Rails Acts As Authenticated Plugin
  2. Repair A Crashed MySQL Table
  3. Raising Model Errors In Rails
  4. Hear Me Ro(a)R
  5. Acts As Voteable Rails Plugin
  6. Acts As Bookmarkable Plugin


13 Responses to “Rails Single Table Inheritance”

  • Kapslok Says:

    A quick question: would you still have controllers for Administrator, Editor and User, or just a single one for User? This stuff is confusing. Is it possible to have an ActiveRecord model inherit from another ActiveRecord model – so as an example you extend the original User model with additional fields in a Editor model?

    On a side note:
    Your db table definition will restrict you user.type to 10 characters, so your example of specifying ‘Administrator’ will fail.

  • TechKnow Says:

    @Kapslok – Yes, an Administrator model can extend the User model. The name of the database table would be users. The users table would store both administrator and regular end users.

    In general, a model can extend from any other model or from ActiveRecord directly. The name of the database table would be the plural of the class that extends ActiveRecord directly.

    A model does not have to be paired with a controller so you don’t have to have a controller for each model.

    Thanks, for letting me know about the the column type being 10 character wide. I originally named the administrator class Admin.

  • James Darling Says:

    Thanks for this, I’ve been doing some rather confusing Single Table Inheritance stuff for the first time recently, and this has been (and will continue to be) a very good resource.

  • Chemica Says:

    Crisp, clear and to the point. Ever thought of writing for the RoR Wiki? ;)

  • 4 Essential & 7 Optional Ruby on Rails Tutorials « BendTheBlock Says:

    [...] 6. OO Inheritance (RoR supports Single Table Inheritance) – Rails Single Table Inheritance[...]

  • adit Says:

    thank’s for the explain

    i just realize STI in ruby on rails is very simple, and the part i like is, it don’t need to create additional table, just create additional model

  • LG Says:

    It looks like to_xml does weird stuff with STI. Consider

    user = User.find(3)
    puts user.class

    This gives Administrator as above. However, then do

    user.to_xml

    It comes back looking like:

    Barb

    I want to have the outer XML wrapper still be and have administrator inside the XML as a or something. Any way to do that without writing a substitute to_xml function?

    TIA

  • mitch Says:

    Hi. Thanks for the post.

    One point: Shouldn’t your Administrator model inherit from User? It is inheriting from Editor in your example.

  • don Says:

    The Administrator model can inherit from either Editor or User. If it inherits from Editor, it has all of the privileges of Editor, so it makes more sense to inherit from it.

  • Pratik Says:

    Thanks for the information. Can i create a separate table for Administrator and Editor if i want to store custom attributes. I mean the attributes for Administrator and Editor which are not generic and cannot be fitted into the User model.

  • Jolmash Says:

    I have some question, I’d thank you guys if you can help me, I have the same question than Pratik: how do you handle custom attributes for each role? I wouldn’t like to have one table per role. another question is: could the type column be replaced by a dynamic attribute in the model? thanks in advance

  • Cookie Says:

    Can we put all the inherited models in the same file along with the parent class? When I try to do model.singularize.classify.constantize, I get a “Uninitialized contant model”. Weird thing is, it works okay on the console, but not when I run the app. Thanks

  • Geek Mama » Blog Archive » The TYPE Column Says:

    [...] to get the most out of your table relationships at guides.rubyonrails.org.  And I ran across a post by Techknow that does a great job of describing Single Table [...]

Leave a Reply