我在ActiveRecord中有以下关系:Annotation
有很多AnnotationGroups
,每个AnnotationNote
(是的,音符在AG上,而不是基础Annos上(。
Annotation.rb
has_many :annotation_groups, :dependent => :destroy
AnnotationGroup.rb
belongs_to :annotation
has_one :annotation_note, :foreign_key => 'annotation_group_id'
注释注释.rb
belongs_to :annotation_group
现在,我正在尝试使用以下范围急切加载一系列注释、它们的组和它们的组的注释:
Annotation.rb
scope :flattened_by_group, ->(group_id) {
includes(:annotation_groups => :annotation_note).where({
'annotation_groups.group_id' => group_id
})
}
以下是应触发急切负载的调用:
Annotation.flattened_by_group(group.id).as_json()
SQL似乎确实提取了足够的数据来完成工作:
SQL (0.6ms) SELECT "annotations"."id" AS t0_r0, (annotations cols trimmed) "annotation_groups"."id" AS t1_r0, (anno_groups cols trimmed) "annotation_notes"."id" AS t2_r0, "annotation_notes"."document_id" AS t2_r1, "annotation_notes"."annotation_group_id" AS t2_r2, "annotation_notes"."note" AS t2_r3, "annotation_notes"."addressed" AS t2_r4, "annotation_notes"."created_at" AS t2_r5, "annotation_notes"."updated_at" AS t2_r6 FROM "annotations"
LEFT OUTER JOIN "annotation_groups" ON "annotation_groups"."annotation_id" = "annotations"."id"
LEFT OUTER JOIN "annotation_notes" ON "annotation_notes"."annotation_group_id" = "annotation_groups"."id"
WHERE "annotation_groups"."group_id" = 81
这是as_json
代码,我开始遇到问题:
def as_json(opts={})
anno_group = annotation_groups[0]
opts.merge({:skip_groups => true})
canonical(opts).merge({
'document_id' => document_id,
'account_id' => account_id,
'organization_id' => organization_id,
'annotation_group_id' => anno_group.id,
'approved_count' => anno_group.approved_count,
'qa_approved_by' => anno_group.qa_approved_by,
'qa_note' => anno_group.annotation_note ? anno_group.annotation_note.note : nil
})
end
当annotation_groups[0]
执行时,不会触发任何查询,向我表明急切加载有效。 但是,在anno_group.annotation_note
检查(或其任何变体(时,每次都会执行一个新查询,获取该特定annotation_group的注释(即使只是检查对象是否为 nil(。
组(正在预先加载,而不是子对象(注释注释(,即使其字段在查询中从 includes
子句正确返回
===
按照 Rails 急切加载逻辑,我怀疑问题源于那些与数据库中任何内容都不匹配的记录(因此 AnnotationNote 没有数据,因此没有创建(。 有没有办法在不向数据库触发另一个查询的情况下检查此 nil 状态?
因此,从我对 Rails 逻辑的挖掘中发现,如果从表中连接的行的 id NULL
,则"预先加载"不会为关联创建空白对象。 检查对象是否是使用关联的.nil?
创建的,将运行查询来查找它,从而违背了预先加载的目的。
因为这是一个has_one
关系,所以检查它是否已加载并没有我能找到的花哨功能,就像loaded?
对has_many
关系所做的那样。 所以我最终要做的是检查AnnotationGroup
对象的annotation_cache
中是否存在annotation_note
。 相关代码更改如下:
'qa_note' => anno_group.association_cache.keys.include?(:annotation_note) ? anno_group.annotation_note.note : nil