I want to query the results of private_classes. The scenario is:
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 has the attribute private_school_id.
I am doing:
s = Student.find(9)
s.joined_private_schools
which results in:
=> #<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">]>
If I do:
c = s.joined_private_schools.includes(private_school: :private_classes)
it results in:
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">]>
But that is still the wrong results.
I need to get the results of private_classes using one query so I can avoid multiple each loops.
If you want to have PrivateClass, you're starting from the wrong point (User). You need to start from PrivateClass joining all the intermediary tables and using the user id as 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})
You can use :through on associations (at least in Rails 4.2)
I updated this, I first missed that you wanted private_classes
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With