Topic: Using Single Table Inheritace with drop down lists

I'm having a little trouble working out how to classify which 'type' a record should be based on Single Table Inheritance.

Let's say I have a table Contacts which has some fields like Name, PhoneNumber, etc. but also has a drop down field that has values such as "Personal", "Professional", "Company", etc.

Now I have a model called Contact and it has some sub classes. The code looks like:

class Contact < ActiveRecord::Base
end

class ContactPersonal < Contact; end
class ContactProfessional < Contact; end
class ContactCompany < Contact; end

etc.

I'm essentially having two issues.

1. How do I get a list of these subclasses for automatically populating the drop down list?

2. Where is the best place to decide what type of object to create. Would a case statement in the controller, based off the selected drop down list item, be the best place, or is there a better way?

TIA
Salty Pete

Re: Using Single Table Inheritace with drop down lists

PeteSalty wrote:

1. How do I get a list of these subclasses for automatically populating the drop down list?

That is tricky because Ruby does not provide an easy way to fetch this information. I suggest doing it manually (create a method/constant in the base Contact class that contains an array of types). I have heard of a hack which you can do to fetch the subclasses, but I'd have to look it up. Let me know if you need that.

PeteSalty wrote:

2. Where is the best place to decide what type of object to create. Would a case statement in the controller, based off the selected drop down list item, be the best place, or is there a better way?

This is what I have done in the past:

# in User model
def self.inheritance_column
  'kind'
end

def self.kinds
  ['Member', 'Admin']
end

# in view
<%= f.select :kind, User.kinds %>

# in controller
def update
  @user = User.find(params[:id])
  @user.kind = params[:user][:kind] # Seems "kind" protected from mass assignment so you need to do this
  if @user.update_attributes(params[:user])
    flash[:notice] = "Successfully updated profile"
    redirect_to #...
  else
    render :action => 'edit'
  end
end


Notice I switched to "kind" as the inheritance column. This is because there is a conflict with Ruby's original "type" method which makes generating the select menu a pain - much easier to just rename the column.

Last edited by ryanb (2006-11-16 13:26:27)

Railscasts - Free Ruby on Rails Screencasts

Re: Using Single Table Inheritace with drop down lists

Thanks a bunch - this certainly explains a lot and actually helps out on a few other issues I've been having.

Once again, thanks.