在这类情况下,我觉得有用反转在我的头上的关系。你想要什么东西?从该模型开始,查询变得更容易思考。
这给了我们:
User.joins(doctor_relationships: :doctor).where(doctor_relationships: {visited: true, doctor: @doctor})
虽然这将让你你在寻找什么,它的丑陋。让我们改进它!
现在我假设你的类是这样的:
class User < ActiveRecord::Base
has_many :doctor_relationships
has_many :doctors, through: :doctor_relationships
end
class DoctorRelationship < ActiveRecord::Base
belongs_to :user
belongs_to :doctor
end
class Doctor < ActiveRecord::Base
has_many :doctor_relationships
has_many :users, through: :doctor_relationships
end
我觉得这是一个要好很多,如果你能对这种情况下的东西,如查询:
doctor.visits
doctor.patients
要做到这一点,你需要修改模型如下:
class Doctor < ActiveRecord::Base
has_many :doctor_relationships
has_many :visits, -> { where(visited: true) }, class_name: 'DoctorRelationship'
has_many :patients, through: :visits, source: :user
has_many :users, through: :doctor_relationships
end
我们在这里做的是告诉活动记录,我们是这样一个联合体,visits
,当visited
场true
上DoctorRelationship
,只有存在。然后,我们使用该关联来定义另一个关联,patients
,它只会返回实际访问过医生的那些用户。
这种方法(除了可读的代码)的好处是,它也产生高效的查询:
SELECT "users".* FROM "users" INNER JOIN "doctor_relationships" ON "users"."id" = "doctor_relationships"."user_id" WHERE "doctor_relationships"."doctor_id" = ? AND "doctor_relationships"."visited" = 't'
这恰好是完全相同的查询,在开始了更详细的ActiveRecord的代码给了我们。得分了!