3 votes

Comment obtenir les résultats d'autres tables à l'aide d'inclusions ou de jointures en Ruby on Rails ?

Je veux interroger les résultats de private_classes. Le scénario est le suivant :

class PrivateClass < ActiveRecord::Base
  belongs_to :private_school
  has_many :lesson_plans
end

class JoinedPrivateSchool < ActiveRecord::Base
  belongs_to :student
  belongs_to :private_school
end

class PrivateSchool < ActiveRecord::Base
  belongs_to :teacher
  has_many :private_classes
  has_many :joined_private_schools
end

class Student < ActiveRecord::Base
  has_many :joined_private_schools
end

JoinPrivateSchool a l'attribut private_school_id .

Je le fais :

s = Student.find(9)

s.joined_private_schools

ce qui entraîne :

=> #<ActiveRecord::Associations::CollectionProxy [#<JoinedPrivateSchool id: 8,
 user_id: 73, student_id: 9, private_school_id: 28, created_at: "2017-02-16 
12:38:37", updated_at: "2017-02-16 12:38:37">, #<JoinedPrivateSchool id: 9,
 user_id: 73, student_id: 9, private_school_id: 33, created_at: "2017-02-16 
12:42:01", updated_at: "2017-02-16 12:42:01">, #<JoinedPrivateSchool id: 12, 
user_id: 73, student_id: 9, private_school_id: 32, created_at: "2017-02-16 
13:19:02", updated_at: "2017-02-16 13:19:02">]>

Si je le fais :

c = s.joined_private_schools.includes(private_school: :private_classes)

il en résulte :

JoinedPrivateSchool Load (0.6ms)  SELECT "joined_private_schools".* FROM 
"joined_private_schools" WHERE "joined_private_schools"."student_id" = $1 
 [["student_id", 9]]

PrivateSchool Load (0.9ms)  SELECT "private_schools".* FROM "private_schools" 
WHERE "private_schools"."id" IN (28, 33, 32)  ORDER BY 
"private_schools"."created_at" DESC

PrivateClass Load (0.7ms)  SELECT "private_classes".* FROM "private_classes" 
WHERE "private_classes"."private_school_id" IN (33, 32, 28)  ORDER BY 
"private_classes"."created_at" DESC

=> #<ActiveRecord::AssociationRelation [#<JoinedPrivateSchool id: 8, user_id: 
73, student_id: 9, private_school_id: 28, created_at: "2017-02-16 12:38:37",
 updated_at: "2017-02-16 12:38:37">, #<JoinedPrivateSchool id: 9, user_id: 73,
 student_id: 9, private_school_id: 33, created_at: "2017-02-16 12:42:01", 
updated_at: "2017-02-16 12:42:01">, #<JoinedPrivateSchool id: 12, user_id: 73,
 student_id: 9, private_school_id: 32, created_at: "2017-02-16 13:19:02", 
updated_at: "2017-02-16 13:19:02">]> 

Mais ce sont toujours les mauvais résultats.

J'ai besoin d'obtenir les résultats de private_classes en utilisant une seule requête afin d'éviter de multiples boucles each.

2voto

rockskull Points 798

Si vous voulez avoir PrivateClass vous partez du mauvais point ( User ). Vous devez commencer par PrivateClass en joignant toutes les tables intermédiaires et en utilisant l'identifiant de l'utilisateur comme condition :

PrivateClass.joins(private_school: :user).where(user: {id: 9})

# or a little more performant (avoids one join)

PrivateClass.joins(:private_school).where(private_school: {user_id: 9})

2voto

244an Points 1074

Vous pouvez utiliser :through sur les associations (au moins dans Rails 4.2)
J'ai mis à jour ceci, j'ai d'abord manqué que vous vouliez des classes privées.

class JoinedPrivateSchool < ActiveRecord::Base
  belongs_to :student
  belongs_to :private_school
  has_many :private_classes, through: :private_schools
end

class Student < ActiveRecord::Base
  has_many :joined_private_schools
  has_many :private_classes, through: :joined_private_schools
end

s = Student.find(9)
s.private_classes

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X