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"
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.