Skip to content

Latest commit

 

History

History
66 lines (53 loc) · 3.76 KB

2008-09-28-multiple-user-access-levels.markdown

File metadata and controls

66 lines (53 loc) · 3.76 KB
wordpress_id layout title wordpress_url
274
post
Single Table Inheritance

This tutorial was written using Ruby 1.8.6, Rails 2.1.

A lot of the time I see people asking how they can do something like access levels for their Rails applications and this usually boils down to some STI (single table inheritance) love. You'll need to have restful_authentication installed.

What is Single Table Inhertiance?

Single Table Inheritance is where you have multiple models that inherit from a single table, hence the name. It's great for situations like this where we want multiple user access levels, but we don't want to create multiple tables for the different kinds of users of our application.

Okay.. so how do I use it?

Firstly you start off with one model that inherits from ActiveRecord::Base, and I would advise running script/generate authenticated person session to get this:

app/models/person.rb

class Person < ActiveRecord::Base

end

And then you subclass some other classes from Person app/models/student.rb

class Student < Person

end

app/models/teacher.rb

class Teacher < Person

end

app/models/admin.rb

class Admin < Person

end

The great thing about splitting these into individual files is because they're more easily managed and closely follows the convention of one model per file.

Now you have a person, student and teacher model and you should have a brand new migration for your people table in db/migrate so go on and open that up and you'll see something like this:

class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table "people", :force => true do |t|
      t.column :login,                     :string, :limit => 40
      t.column :name,                      :string, :limit => 100, :default => '', :null => true
      t.column :email,                     :string, :limit => 100
      t.column :crypted_password,          :string, :limit => 40
      t.column :salt,                      :string, :limit => 40
      t.column :created_at,                :datetime
      t.column :updated_at,                :datetime
      t.column :remember_token,            :string, :limit => 40
      t.column :remember_token_expires_at, :datetime

    end
    add_index :people, :login, :unique => true
  end

  def self.down
    drop_table "people"
  end
end

To enable STI for this table, just add:

t.column :type, :string

into the create_table block, just after t.column :remember_token_expires_at, :datetime. This type column will be set to whatever class the record is, so if we create a new Student object, this type column will be set to "Student".

Controllers

To create new objects for these subclasses I would recommend building a people controller and using the form partial from that to base your form off from the other controllers, such as StudentsController and TeachersController. These controllers should NOT subclass from PeopleController, they should be their own independent controllers because Teachers, People and Students are all individual resource types.

Associated Models

If you have associated models (e.g. Person has_many :enrolments), any subclass of Person will inherit this relationship. For the relationship, this will be referenced via person_id still in the enrolments table.