Designing a Rails application: single table inheritance?
Asked Answered
P

1

9

I've been researching this for a few days now, and I know there is an abundance of articles that talk about single table inheritance and polymorphic associations with Rails. A lot of helpful material is from 2009 or before and I'm wondering if there is a better approach to this problem now.

The situation

The application has a couple of different user types (ie, Buyer and Seller), each of which have a profile. The profile for each user type is really different, so I'm currently ruling out the idea of one generic "profile" table.

My current approach

which is the same as this solution.

class User < ActiveRecord::Base
  # authentication stuff
end

class UserType1 < User
  has_one :user_type_1_profile
end

class UserType2 < User
  has_one :user_type_2_profile
end

...

class UserTypeN < User
  has_one :user_type_n_profile
end

Based on my research, this is kind of a "mixed model" design.

Honestly, at this point I don't know of any other solution that would work. Every time I've seen similar questions asked I see the idea of polymorphic associations brought up. Could someone elaborate how a polymorphic association would work in this case?

Does anyone have any other design suggestions?

Pentimento answered 10/10, 2011 at 22:54 Comment(0)
T
6

You would be better off with a polymorphic association here with various profile types.

class User < ActiveRecord::Base
  belongs_to :profile, :polymorphic => true
end

class ProfileTypeA < ActiveRecord::Base
  has_one :user, :as => :profile
end

class ProfileTypeB < ActiveRecord::Base
  has_one :user, :as => :profile
end

Which would require you have a migration/table like this:

change_table :users do |t|
  t.integer :profile_id
  t.string :profile_type
  # OR (same thing, the above is more explicit)
  t.references :profile, :polymorphic => true
end

There's more info on this in the Guide: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

Tyrant answered 10/10, 2011 at 23:18 Comment(5)
This makes sense to me now. Do you mind pointing out the benefits of this design over my original approach? I believe that this method is beneficial, but it would be nice for me to understand why.Pentimento
This accurately models the data you're representing, at least as I understand it. STI is more for when you have many different objects that share common functionality. You don't have that. You have users that all have profiles that have different behavior.Tyrant
I understand this now and that makes a lot sense. Thanks!Pentimento
Is there a way to use accepts_nested_attributes_for :profile on the User model, or do I need to use it on each individual profile model?Pentimento
Note the typo in the migration example: (correct) change_table :users do |t| t.references :profile, :polymorphic => true endGooseberry

© 2022 - 2024 — McMap. All rights reserved.