返回每个父关系并过滤子句where子句活动记录

时间:2015-11-14 23:42:45

标签: ruby-on-rails ruby activerecord

我有父母,孩子,技能的关系。每个父母可以有几个孩子,每个孩子都有一个技能。

我想从数据库中返回所有父母,如果他们具有某种技能,则包括属于他们的孩子。

在查询结束时,我们将有几个父母可能有0个孩子。我尝试这样的事情Parent.includes(children: [:skill]).where(skill: {skill_type: type}),但这并没有让所有的父母都回归。这可以通过ActiveRecord完成吗?

1 个答案:

答案 0 :(得分:1)

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实际上并没有让你选择按照你想要的方式预先加载哪些关联。