Please notice, this is not a question about adding a WHERE condition to an association but a rather advanced question about how to alter the JOIN clause when using eager
This does not solve the problem stated.
You cannot alter the JOIN generated by calling eager_load
like you want. The WHERE clause is your only option, and it has the exact same effect as the condition on your JOIN. Here it is, even if you didn't want it:
Parent.eager_load(:grades).where("grades.level = 'A+'")
If I am right, you only want to eager load the subset of the associations. Well, in order to do so, you need to outsmart the rails . You can basically create another association such as "highest_grade" to fetch the grades with level A+ using a where clause inside the ruby lambda. This can be achieved by using the following snippet of code
class Parent
has_many :children
has_many :grades, through: :children
has_many :highest_grade, ->{where(level: 'A+')}, class_name: "Grade", through: :children
end
Now you need to eager load the highest_grade association.
Parent.eager_load(:highest_grades)
This will essentially load all the parents along with only those grades whose level is A+.
It generates the following query.
SQL (0.3ms) SELECT `parents`.`id` AS t0_r0, `parents`.`created_at` AS t0_r1, `parents`.`updated_at` AS t0_r2, `grades`.`id` AS t1_r0, `grades`.`child_id` AS t1_r1, `grades`.`created_at` AS t1_r2, `grades`.`updated_at` AS t1_r3, `grades`.`level` AS t1_r4 FROM `parents` LEFT OUTER JOIN `children` ON `children`.`parent_id` = `parents`.`id` LEFT OUTER JOIN `grades` ON `grades`.`child_id` = `children`.`id` AND `grades`.`level` = '
If you want to understand how does this work. Please use this link as a reference