Rails 4的范围是find没有孩子的父母

我发现一个答案有一些可用的例子,可以find有n孩子的父母,但是find没有孩子的父母也是一样(大概是因为join排除了他们)。

 scope :with_children, joins(:children).group("child_join_table.parent_id").having("count(child_join_table.parent_id) > 0") 

任何人都可以指向正确的方向吗?

这应该做你想要的工作:

Rails 3&4

 scope :without_children, includes(:children).where(:children => { :id => nil }) 

这里最大的区别就是joins成为一个includes :一个包含加载所有的关系,如果它们存在,连接将只加载关联的对象,忽略没有关系的对象。

实际上, scope :with_children, joins(:children)应该足以返回至less有一个孩子的Parent。 试试看!

Rails 5

请参阅下面的@ Anson的答案


正如@MauroDias所指出的那样, 如果它是你父母和孩子之间的自我指涉关系那么上面的代码将不起作用。

通过一点研究,我发现了如何做到这一点:

考虑这个模型:

 class Item < ActiveRecord::Base has_many :children, :class_name => 'Item', :foreign_key => 'parent_id' 

如何退回所有没有孩子的物品(ren):

 Item.includes(:children).where(children_items: { id: nil }) 

我怎么findchildren_items表?

Item.joins(:children)生成以下SQL:

 SELECT "items".* FROM "items" INNER JOIN "items" "children_items" ON "children_items"."parent_id" = "items"."id" 

所以我猜想Rails在自引用的情况下需要一个JOIN时使用一个表。


类似的问题:

  • 如何根据属于第一个模型的另一个模型的属性来查询模型?
  • Rails活动logging查询与“存在”的关联
  • Rails 3,has_one / has_many和lambda条件
  • join多个具有活动logging的表格

@MrYoshiji有一个坚实的Rails 4的答案,但对于Rails 5来到这里的人来说,你有更多的select。

使用Rails 5:

从Rails 5开始,还可以使用left_outer_joins来避免加载关联。 它在拉取请求#12071中被引入。

 scope :without_children, left_outer_joins(:children).where(children: { id: nil }) 

对于有孩子的父母来说,Yoshiji先生的Rails 4解决scheme仍然是一个可以使用的解决scheme:

 scope :with_children, joins(:children)