Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Associations Through Multiple Levels

I am relatively new to Rails and am working on a project that involves multiple, "nested" levels of data. I am having issues making the proper associations so I can get all the child elements of a model 3 levels higher. Here is an example of the models:

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

I have implemented a relationship in the Country model, has_many :cities, :through => :states and have tried to call Country.first.cities.all, which works. However, I am having issues accessing all the people in a given country when I try Country.first.cities.all.people.all in the People controller.

What is the best way to deal with this sort of association situation? Should I add a foreign key to each of the children tables, such as country_id, so that I can get all the People in a Country? Any suggestions would be appreciated.

like image 906
theandym Avatar asked Feb 27 '11 17:02

theandym


2 Answers

The reason is that Country.first.cities.all is an array, and each of it's elements has the method people, instead of the entire collection of cities. You'll notice that this works:

Country.first.cities.first.people.all

Because the first city of the first country has the people method. To get a list of all people in a country, you could do the following in a single query:

People.joins(:city => {:state => :country})
  .where(:country => {:id => Country.first.id}).all
like image 94
Pan Thomakos Avatar answered Nov 07 '22 11:11

Pan Thomakos


It's beacouse

Country.first.cities.all

is a collection of cities and it doesn't have people method.

You should go with

Country.first.cities.all.each do |city|
    city.people
end
like image 31
Adrian Serafin Avatar answered Nov 07 '22 09:11

Adrian Serafin