代码之家  ›  专栏  ›  技术社区  ›  brad

activerecord查找具有关联子级的所有父级

  •  10
  • brad  · 技术社区  · 14 年前

    我不知道为什么我搞不懂,我觉得应该很简单。我有两个模型(见下文)。我正在尝试为SupplierCategory创建一个命名作用域,该作用域将查找关联供应商不为空的所有SupplierCategory(包括:供应商)。

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

    目前我正在使用:

    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 回复  |  直到 9 年前
        1
  •  12
  •   Harish Shetty    9 年前

    还有一种方法:

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

    因为rails使用 OUTER 参加 include 条款.如果找不到匹配的行,查询将为供应商列返回空值。因此 NOT NULL check返回匹配的行。

    轨道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
    
        2
  •  3
  •   fl00r    14 年前
    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
    

    使用命名作用域的另一种更灵活的方法

    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
    
        3
  •  3
  •   klew    14 年前

    更简单的版本:

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

    如果你想经常使用它,考虑使用 counter_cache .

        4
  •  1
  •   Ju Nogueira    14 年前

    我想应该是

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

    我相信这是更快的方法。