使用包含在不相关模型上的预加载

时间:2015-04-16 15:15:32

标签: sql ruby-on-rails postgresql activerecord

假设我有三个模型,设置如下:

class Student < ActiveRecord::Base
  has_many :tests
  has_many :cars
end

class Car < ActiveRecord::Base
  belongs_to :student
end

class Test < ActiveRecord::Base
  belongs_to :student
end

我想查询学生没有车的所有考试。预加载。

我尝试了以下内容:

Test.includes(:cars) # does not work because the two are not associated
Test.joins('inner join cars ON tests.student_id = cars.student_id') # works, but it doesn't preload the Cars model in my result

我不想创建has_many :through关系,因为它们实际上根本不相关,但如果这是最好的解决方案,我不反对。

思想?

Rails 4.1.5
PostgreSQL 9.3.4
红宝石2.1.2

2 个答案:

答案 0 :(得分:2)

跨三个表的连接是一种低效的方法。 Rails甚至可能足够聪明地实现这一点并将其拆分为单独的数据库查询。

我会这样做,它有两个简单的查询

student_ids_with_car = Car.select("student_id").distinct
@tests = Test.where("student_id not in (?)", student_ids_with_car)

答案 1 :(得分:1)

您不必同时将has_many :through用于这些关联的关联和关联。

Test.includes(:student => :cars)

将包括学生及其汽车(默认情况下,它会预先加载,您可以使用eager_load代替preload来强制使用基于联接的加入。