Rails: как мне смоделировать предпочтения?Должен ли я использовать has_many: through? - PullRequest
1 голос
/ 10 декабря 2010

У меня есть две модели: User и HairColor. У пользователя есть только один цвет волос, но он может иметь множество предпочтений цвета волос. Какой лучший способ смоделировать это?

Вот что я начал делать:

#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

Использует ли has_many: правильный ли подход? А что если я захочу расширить это на другие атрибуты, такие как «цвет глаз»? (У пользователя один цвет глаз, но он может предпочесть много цветов глаз "

1 Ответ

1 голос
/ 10 декабря 2010

Количество цветов волос будет ограничено, поэтому таблица предпочтений должна иметь hair_color_id и быть настроена так:

#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

Я верю, что это правильно. Дайте мне знать, если вы столкнетесь с какими-либо препятствиями.


Когда вы добавляете цвет глаз или любую другую характеристику, вам, вероятно, придется делать что-то другое с предпочтениями. В этот момент у меня будет 4 столбца: id, user_id, foreign_id, foreign_type

foreign_id будет идентификатором из таблицы eye_color / hair_color, а foreign_type будет "eye" или "hair" или чем-то другим. Тогда в вашей модели у вас будет что-то вроде этого:

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

Это немного сходит с ума, но это самый СУХОЙ способ сделать это. Вы добавили бы то же самое в свой eye_color.rb и просто заменили «hair» на «eye» для foreign_type.

...