CTI in ActiveRecord

To my knowledge rails only supports STI or separate tables for each subclass. If you make People abstract then each subclass will be in its own tale.

The hybrid you show is not directly supported. You would need to model them as associated tables. But, if you think about it that makes sense. How would you expect a row in the employee table to connect to a row in the people table? The best way is to add a people_id to employee. That becomes a :belongs_to and you are all set. You can always add support in Employee for delegating to the associated people object so to the user they appear to be subclasses.


In Rails you can use STI very easily. The following example should clearify things (from Agile Web Development with Rails, you should buy the book at http://www.pragmaticprogrammer.com/ ):

create_table :people, :force => true do |t|   t.column :type, :string

  # common attributes   t.column :name, :string   t.column :email, :string

  # attributes for type=Customer   t.column :balance, :decimal, :precision => 10, :scale => 2

  # attributes for type=Employee   t.column :reports_to, :integer   t.column :dept, :integer

  # attributes for type=Manager   # - none - end

class Person < ActiveRecord::Base end

class Customer < Person end

class Employee < Person   belongs_to :boss, :class_name => "Employee" , :foreign_key => :reports_to end

class Manager < Employee end

Customer.create(:name => 'John Doe' , :email => "john@doe.com" , :balance => 78.29) wilma = Manager.create(:name => 'Wilma Flint' , :email => "wilma@here.com" ,:dept => 23) Customer.create(:name => 'Bert Public' , :email => "b@public.net" ,:balance => 12.45) barney = Employee.new(:name => 'Barney Rub' , :email => "barney@here.com" ,:dept => 23) barney.boss = wilma barney.save!

manager = Person.find_by_name("Wilma Flint" ) puts manager.class #=> Manager puts manager.email #=> wilma@here.com puts manager.dept #=> 23

customer = Person.find_by_name("Bert Public" ) puts customer.class #=> Customer puts customer.email #=> b@public.net puts customer.balance #=> 12.45

Regards, Bas