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.
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. 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".
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.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.