1

I have two models: User and HairColor. A user has only one hair color, but can have many hair color preferences. What's the best way to model this?

Here's what I started to do:

#models/user.rb class User < ActiveRecord::Base belongs_to :hair_color has_many :preferences, has_many :hair_colors, :through => :preferences end #models/hair_color.rb class HairColor < ActiveRecord::Base has_many :users end #models/preference.rb class Preference < ActiveRecord::Base belongs_to :user belongs_to :hair_color end 

Is using has_many :through the right approach? Also what if I want to extend this to other attributes such as "eye color"? (A user has one eye color, but can prefer many eye colors"

1 Answer 1

1

There will be a limited amount of hair colors, so the preference table needs to have a hair_color_id and be set up like so:

#models/user.rb class User < ActiveRecord::Base has_one :hair_color has_many :preferences end #models/hair_color.rb class HairColor < ActiveRecord::Base belongs_to :user belongs_to :preference end #models/preference.rb class Preference < ActiveRecord::Base belongs_to :user has_many :hair_color end 

I believe that's correct. Let me know if you run into any snags.


When you add eye color or any other characteristic, you'll probably have to do something different with preference. I'd have 4 columns at that point: id, user_id, foreign_id, foreign_type

foreign_id would be the id from the eye_color/hair_color table, and foreign_type would be "eye" or "hair" or something. Then in your model, you'd have something like this:

#models/hair_color.rb class HairColor < ActiveRecord::Base belongs_to :user has_many :preferences, :foreign_key => :foreign_id, :conditions => { "preferences.foreign_type" => "hair" } end 

That gets a little crazy, but it's the most DRY way of doing it. You'd put the same thing in your eye_color.rb and just replace "hair" with "eye" for the foreign_type.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks! Will try this out. Also, to add other preferences such as Eye Color, would I just need to add an eye_color_id column to the preference table? Or should I separate the preferences into distinct models, such as "HairColorPreference" and "EyeColorPreference"? Not sure which would be the most DRY.
Updated for further question.
Chuck, this is great. I was tearing my hair out trying to figure out and understand the has_many :through association. This does seem like the most DRY approach. So now, I'll try it out and then attempt to get a form working for selecting preferences within a view template. New to Ruby on Rails, but hopefully it's not too hard. Thanks!
No problem man! Rails is really confusing when you first get started, but after a while you start to appreciate it's conventions and the "magic" that goes on behind the scenes. Good luck!
Also, for future reference, most people I've seen use :through as simply a way to change their naming conventions. So if you wanted User.Choices, you'd have to put :has_many :choices, :through => :preferences. There are other uses for it, but don't over-estimate it's utility.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.