Ассоциации Rails через несколько уровней

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

class Country < ActiveRecord::Base
  has_many :states
end

class State < ActiveRecord::Base
  belongs_to :country
  has_many :cities
end

class City < ActiveRecord::Base
  belongs_to :state
  has_many :people
end

class Person < ActiveRecord::Base
  belongs_to :city
end

Я реализовал отношения в модели Country, has_many :cities, :through => :states и попытался вызвать Country.first.cities.all, и это работает. Однако у меня возникают проблемы с доступом ко всем людям в данной стране, когда я пытаюсь использовать Country.first.cities.all.people.all в контроллере People.

Каков наилучший способ справиться с такой ассоциативной ситуацией? Должен ли я добавить внешний ключ к каждой из дочерних таблиц, например country_id, чтобы я мог получить все People в Country? Мы ценим любые предложения.


person theandym    schedule 27.02.2011    source источник
comment
Вы можете использовать named_scopes или scopes (в Rails 3). Для этого тоже есть хороший railscast!.   -  person Shreyas    schedule 27.02.2011


Ответы (2)


Причина в том, что Country.first.cities.all — это массив, и каждый его элемент имеет метод people, а не весь набор городов. Вы заметите, что это работает:

Country.first.cities.first.people.all

Потому что в первом городе первой страны есть народный метод. Чтобы получить список всех людей в стране, вы можете сделать следующее в одном запросе:

People.joins(:city => {:state => :country})
  .where(:country => {:id => Country.first.id}).all
person Pan Thomakos    schedule 27.02.2011
comment
Этот ответ может быть старым, но он очень помог мне понять, как работать с (3 и 4) вложенными соединениями, я пытался сделать это в обратном порядке и, конечно, если это не сработало. Теперь это даже легко понять! Спасибо - person helenatxu; 18.12.2020

это потому что

Country.first.cities.all

представляет собой набор городов, и у него нет метода людей.

Вы должны пойти с

Country.first.cities.all.each do |city|
    city.people
end
person Adrian Serafin    schedule 27.02.2011