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

时间:2010-04-29 12:01:43

标签: ruby-on-rails activerecord associations

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

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

目前我正在使用:

named_scope :with_suppliers, :include => :suppliers

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

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

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

课程定义

class SupplierCategory < AR
  has_many :suppliers, :order => "name"
end

class Supplier < AR
  belongs_to :supplier
end

4 个答案:

答案 0 :(得分:12)

这是另一种方法:

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

这是有效的,因为Rails对OUTER子句使用include JOIN。如果未找到匹配的行,则查询将返回供应商列的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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

更简单的版本:

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

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

答案 3 :(得分:1)

我相信它会像

#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"

我相信这是更快的方式。