ActiveRecord找到所有有关联孩子的父母

我不知道为什么我无法解决这个问题,我认为应该相当简单。 我有两个型号(见下文)。 我正在尝试为SupplierCategory提出一个命名范围,该范围会找到所有SupplierCategory(包括:供应商),这些供应商的关联供应商不是空的。

我尝试了一个直接加入, named_scope :with_suppliers, :joins => :suppliers商,它只给我供应商的类别,但它给了我每个类别单独列出,所以如果一个类别有2个供应商,我在返回时获得两次类别数组:

目前我正在使用:

 named_scope :with_suppliers, :include => :suppliers 

然后在我看来我正在使用:

  'category', :collection => @categories.find_all{|c| !c.suppliers.empty? } %> 

不完全雄辩,但说明了我想要实现的目标。

类定义

 class SupplierCategory  "name" end class Supplier < AR belongs_to :supplier end 

这是另一种方法:

 named_scope :with_suppliers, :include => :suppliers, :conditions => "suppliers.id IS NOT NULL" 

这是有效的,因为Rails使用OUTER JOIN for include子句。 如果未找到匹配的行,则查询将返回供应商列的NULL值。 因此NOT NULL检查返回匹配的行。

Rails 4

 scope :with_suppliers, { includes(:steps).where("steps.id IS NOT NULL") } 

或者使用静态方法:

 def self.with_suppliers includes(:steps).where("steps.id IS NOT NULL") end 

注意:

这个解决方案渴望加载供应商。

 categories = SupplierCategory.with_suppliers categories.first.suppliers #loaded from memory 
 class SupplierCategory < AR has_many :supliers def self.with_supliers self.all.reject{ |c| c.supliers.empty? } end end SupplierCategory.with_supliers #=> Array of SuplierCategories with supliers 

另一种使用named_scope更灵活的方法

 class SupplierCategory < AR has_many :supliers named_scope :with_supliers, :joins => :supliers, :select => 'distinct(suplier_categories.id), suplier_categories.*', :having => "count(supliers.id) > 0" end SupplierCategory.with_supliers(:all, :limit => 4) #=> first 4 SupplierCategories with suppliers 

更简单的版本:

 named_scope :with_suppliers, :joins => :suppliers, :group => :id 

如果您想经常使用它,请考虑使用counter_cache 。

我相信它会是这样的

 #model SupplierCategory named_scope :with_suppliers, :joins => :suppliers, :select => "distinct(supplier_categories), supplier_categories.*", :conditions => "suppliers.supplier_categories_id = supplier_categories.id" 

请让我知道这对你有没有用。

编辑:使用fl00r的想法:

 named_scope :with_suppliers, :joins => :suppliers, :select => "distinct(supplier_categories), supplier_categories.*", :having => "count(supliers.id) > 0" 

我相信这是更快的方式。