web-dev-qa-db-fra.com

Rails se joint via l'association

Dans Ruby on Rails, je veux trouver des employeurs dans la ville. Disons que les modèles sont configurés de cette façon:

City
has_many :suburbs
has_many :households, :through => suburbs
has_many :people, :through => suburbs

Suburb
has_many :households
has_many people, :through => households
belongs_to :city


Household
has_many :people
belongs_to :suburb

People
belongs_to :household
belongs_to :employer


Employer
has_many :people

J'ai l'impression que je veux qu'une sorte d'employeur rejoigne some_city.people mais je ne sais pas comment faire. Si les gens appartenaient directement aux villes, je pourrais rejoindre Employeur aux gens où city_id est quelque chose, mais je veux trouver les mêmes données sans cette jointure directe et je suis un peu perdu.

Je vous remercie.

30
spitfire109

Vous pouvez faire la jointure comme l'illustre jvans. Ou vous pouvez configurer vos relations comme suit:

class Employer < ActiveRecord::Base
  has_many :people
  has_many :households, through: :people
  has_many :suburbs, through: :households
  has_many :cities, through: :suburbs
end

class Person < ActiveRecord::Base
  belongs_to :household
  belongs_to :employer
end


class Household < ActiveRecord::Base
  belongs_to :suburb
  has_many :people
end

class Suburb < ActiveRecord::Base
  belongs_to :city
  has_many :households
  has_many :people, through: :households
end

class City < ActiveRecord::Base
  has_many :suburbs
  has_many :households, through: :suburbs
  has_many :people, through: :households
  has_many :employers, through: :people
end

Ensuite, vous pouvez joindre City à partir de Employer, et vice-versa, directement.

Par exemple:

Employer.joins(:cities).where("cities.name = ?", "Houston").first

SELECT "employers".* FROM "employers" 
INNER JOIN "people" ON "people"."employer_id" = "employers"."id" 
INNER JOIN "households" ON "households"."id" = "people"."household_id" 
INNER JOIN "suburbs" ON "suburbs"."id" = "households"."suburb_id" 
INNER JOIN "cities" ON "cities"."id" = "suburbs"."city_id" WHERE (cities.name = 'Houston') 
LIMIT 1
19
Sean Hill

Utiliser des jointures imbriquées

Employer.joins({:people => {:household => {:suburb => :city}}}) 

devrait vous donner la table de jointure que vous recherchez. Si vous traversiez l'autre direction, vous utiliseriez des noms pluriels

City.joins( :suburbs => {:households => {:people => :employers }})
42
jvans