views:

2767

answers:

4

Here's what I'm trying to achieve: I have a Users table and each user can be any of a dozen of types: actor, dancer, director,...which is determined after signing up. Each type of user can have any number of profiles. Eg. actors can have any number of actor_profiles, dancers cand have any number of dancer_profiles,...

The problem is how do I link the profile with the user. An obvious solution would be to create an aditional table for each profile type, so that I could use a polymorphic belongs_to in User and then a simple belongs_to in each profile, but that seems less than optimum. An arguably better way would be to tell rails that user it's of type actor, so that user.profiles would work naturally, without any clutter. Does rails support such behaviour, or is there anything better than the former method? Thanks.

+1  A: 

Define the relationships in the subclasses:

class User < ActiveRecord::Base
end

class Actor < User
  has_many :profiles, :class_name => "ActorProfile"
end

class Dancer < User
  has_many :profiles, :class_name => "DancerProfile"
end
pjb3
A: 

I tried that but every time I save an actor, it gets saved simply in User. And even if it would get saved in Actor, would it still be possible to use User.find and find all actors, dancers etc? Ovi PS: I tried to add a comment but it doesn't work.

You should edit your original post instead of replying with an answer.
Matt Olenik
In Rails, sublclasses always get saved in the table of the base class. Read about single table inheritance here http://api.rubyonrails.org/classes/ActiveRecord/Base.html
pjb3
+3  A: 

pjb's answer uses Single Table Inheritance. For this to work you need to add a column called type to your Users and to your Profiles* tables, so that Rails can save what type of User this is (since Actor, Dancer etc. are just subclasses of User).

This means they will all be saved in the users/profiles tables, but when you instantiate them ActiveRecord will instantiate them as the correct type. With this you'll be able to call

User.find

but also do things like

Actor.find, Actor.all, etc

and have it scoped to only Actors

Google rails single table inheritance for more details and examples.

  • Of course you'd need to declare your Profile subclasses the same way you declared your User subclasses

class Profile < ActiveRecord::Base belongs_to :user end

class ActorProfile < Profile end

class DancerProfile < Profile end

etc

luke_randall
A: 

You'll need to make sure that your User table has a column called "type". Rails will save the TYPE of the Class (User, Actor, etc.) in that database field.