我有一个父、子、技能的关系。每个家长可以有几个孩子,每个孩子都有一项技能。
我想从数据库中返回所有家长,并包括属于他们的孩子,如果他们有某种技能的话。
在查询结束时,我们将有几个可能有0个孩子的父母。我正在尝试类似的Parent.includes(children: [:skill]).where(skill: {skill_type: type})
,但这并不能返回所有的Parents。这可以通过ActiveRecord实现吗?
class Parent < ActiveRecord::Base
has_many :children
has_many :skills, through: :children
def self.with_skill(skill_type)
children = Child.joins(:skills).where(skills: { skill_type: skill_type } )
Parent.all.map do |parent|
children = children.select { |c| c.parent_id == parent.id }
# This marks the association as loaded so that rails does not issue a n+1 query
association = parent.association(:children)
association.loaded!
association.target.concat(children)
children.each { |c| association.set_inverse_instance(c) }
parent.readonly! # because we dont want to accidentally set the children to []
parent
end
end
end
这里我们使用两个查询,第一个查询获取具有所选技能和技能的所有子项。第二个得到了所有的父母。
然后,我们手动设置Parent和Child之间的关系,使其parent.children
不会导致ActiveRecord查询数据库中的子级。
我们还将该记录标记为只读,因为如果保存了其中一条记录,则可以从关联的子项中删除parent_id
。
总而言之,这是一个很好地显示记录的工作。Rails并不能真正让您选择应该以您希望的方式预加载哪些关联。