Как я могу присоединиться к одним и тем же 2 моделям дважды в Rails? - PullRequest
2 голосов
/ 16 ноября 2010

У меня есть приложение с настройками страны. У пользователя будет 2 типа предпочтений страны - событие и исследование. В будущем их может быть больше. Я больше склонялся к наличию двух таблиц, чтобы представить это с помощью STI. У меня возникли проблемы с элегантной настройкой Rails для этого. Я мог бы взломать это, но я бы предпочел сделать это по соглашению Rails. Я хочу что-то вроде этого:

class User < ActiveRecord::Base
  has_many event_countries, :through => :event_countries, :class_name => 'Country'
  has_many research_countries, :through => :research_countries, :class_name => 'Country'
end

class EventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class ResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
...
end

Это не работает, хотя. Учитывая этот «псевдокод», кто-нибудь знает, как на самом деле реализовать это в Rails?

1 Ответ

5 голосов
/ 16 ноября 2010

Я думаю, что вы собираетесь объявить их неправильно, потому что это должно работать правильно.Вот для чего нужна директива :through:

class User < ActiveRecord::Base
  has_many :event_countries
  has_many :countries_with_events,
    :through => :event_countries,
    :source => :country

  has_many :research_countries
  has_many :countries_with_researches,
    :through => :research_countries,
    :source => :country
end

class EventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class ResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
  # ...
end

Большая неловкость исходит от ярлыков, которые вы выбрали для таблиц.Хотя на первый взгляд они кажутся разумными, их использование в конечном итоге усложняет их.

Возможно, вы захотите назвать research_countries что-то вроде user_research_countries, чтобы имя отношения могло быть user.research_countriesкак :through:

class User < ActiveRecord::Base
  has_many :user_event_countries
  has_many :event_countries,
    :through => :user_event_countries,
    :source => :country

  has_many :user_research_countries
  has_many :research_countries,
    :through => :user_research_countries,
    :source => :country
end

class UserEventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class UserResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
  # ...
end

Вы можете еще больше изменить это, добавив поле в таблицу сопоставления стран-пользователей, содержащее один или несколько флагов, которые в этом случае будут исследованием или событием или чем-то ещевам потребуется позже:

class User < ActiveRecord::Base
  has_many :user_countries
  has_many :event_countries,
    :through => :user_countries,
    :source => :country,
    :conditions => { :event => true }
  has_many :research_countries,
    :through => :user_countries,
    :source => :country,
    :conditions => { :research => true }
end

class UserCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user

  # * column :event, :boolean
  # * column :research, :boolean
end

class Country < ActiveRecord::Base
  # ...
end
...