2010-04-29 23 views
10

Neden bunu çözemediğimi bilmiyorum, bence oldukça basit olmalı. İki modelim var (aşağıya bakınız). SupplierCategory için, Tedarikçi (ler) in ilişkili Tedarikçi (ler) in boş olmadığı tüm tedarikçileri (tedarikçiler dahil) bulacağını gösteren bir kapsam oluşturmaya çalışıyorum. ActiveRecord, ilişkili çocukları olan tüm ebeveynleri bul

Ben bir dik katılmak bana tedarikçiler ile sadece kategoriler verir named_scope :with_suppliers, :joins => :suppliers çalıştı, ama bana ayrı listelenen her kategoriyi verir, bu yüzden bir kategori 2 tedarikçiler varsa, ben iade dizide iki kez kategori olsun:

Şu anda kullanıyorum: o zaman

named_scope :with_suppliers, :include => :suppliers 

ve bence ben kullanıyorum:

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

tam anlamlı ama illustrat değil ne elde etmeye çalışıyorum.

Sınıf Tanımları

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

class Supplier < AR 
    belongs_to :supplier 
end 
+0

"Subbplier" sınıfında, 'belongs_to: supplier_category'? – klew

cevap

12

İşte bir tane daha yaklaşımdır. Eşleşen satır bulunamadığı zaman, sorgu, tedarikçi sütunları için NULL değerleri döndürür. Dolayısıyla, NOT NULL denetimi, eşleşen satırları döndürür.

Raylar 4

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

Ya statik bir yöntemi kullanarak:

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

Not:

Bu çözüm istekli yükler tedarikçileri.

categories = SupplierCategory.with_suppliers 
categories.first.suppliers #loaded from memory 
+0

düşündüğüm kadar açık değil görünüyor Kesinlikle tüm çözümleri en özlü ve mükemmel çalışıyor! 'kapsamı:: Teşekkürler – brad

+1

raylar 4 için güncellenmiş in_use, -> {içermektedir (: adım) .Where ("steps.id IS NOT NULL")}' ve muadili 'kapsamı: not_in_use, -> { (: steps) .where ("steps.id IS NULL")}} – soychicka

1

Ben bir şey

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

gibi sizin için çalışan varsa söyleyin olacağına inanıyorum.

Düzenleme: fl00r fikrini kullanarak :

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

bu hızlı yolu olduğuna inanıyoruz. Raylar OUTERinclude maddesi için JOIN kullanması nedeniyle

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

Bu çalışır: named_scope kullanarak

+1

supplier_categories yerine model supplier_category'in tekil formlarını kullanmanız gerektiğinden emin misiniz? – fl00r

+0

no = Bunun için Ptks. –

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 

bir başka yolu daha esnek

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 
+0

"Birleştirmenin" kullanılmasının daha hızlı olduğuna inanıyorum, değil mi? Ben onun durumda ilgili olup olmadığını bilmiyorum ... ama merak ediyorum = P –

+0

evet, haklısın, bu yüzden ben – fl00r

+1

katılmak ile çözüm ekledim Kodunuz, birleştirme nedeniyle yinelenen verileri döndürecektir. –

3

basit sürüm:

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

sık kullanmak istiyorsanız, counter_cache kullanmayı düşünün.

+0

+1 özlü içerir. –

İlgili konular