2010-08-03 6 views
6

iki kapsamlarını (ActiveRelations) her birinin farklı bir bulunmaktadır zincirleme bir sorun olduğu görülmektedir içerir kendi başlarına:sorun:</p> <p>iyi çalışır, her ikisi de, bu iki kapsamları göz önünde bulundurun: activerecord (raylar 3.) ile kapsamları zincir raylar 3. olarak

İlk kapsamı:

scope :global_only, lambda { |user| 
includes(:country) 
.where("countries.area_id <> ?", user.area) } 

Work.global_only (kullanıcı) => (okunabilirlik için SQL alanların kesim listesi)

SELECT * FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (countries.area_id <> 3) 

Şimdi ikinci kapsamı:

scope :not_belonging_to, lambda { |user| 
includes(:participants) 
.where("participants.user_id <> ? or participants.user_id is null", user) } 

Work.not_belonging_to (kullanıcı) => (okunabilirlik için SQL alanların kesim listesi) düzgün bireysel olarak bu işin Yani

SELECT * FROM "works" LEFT OUTER JOIN "participants" ON "participants"."work_id" = "works"."id" WHERE (participants.user_id <> 6 or participants.user_id is null) 

hem. Şimdi

, onları bir arada zincirlemek:

Work.global_only (kullanıcı) .not_belonging_to (kullanıcı)

SQL: Gördüğünüz gibi

SELECT (list of fields) FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (participants.user_id <> 6 or participants.user_id is null) AND (countries.area_id <> 3) 

, ikinci kapsamından katılmak tamamen yok sayılır. Bu nedenle SQL, 'böyle bir sütun yok' particip.user_id 'üzerinde başarısız olur. Eğer kapsamları ters sırayla zincirlersek, 'katılımcılar' birliği mevcut olacak ve 'ülkeler' birleşimi kaybolacak. Her zaman kayıp olan ikinci birleşme, öyle görünüyor.

ActiveRecord ile bir böcek gibi bu göz mu, yoksa yanlış bir şey yapıyorum, yoksa bu bir "özelliği" dir :-)

(PS. Evet, biliyorum, ben hem birleştirmeler bir kapsam oluşturabilir Tablolar ve istediğim sonucu doğru bir şekilde vereceğim. Bende zaten var. Ama farklı şekillerde zincirleme yapılabileceğinden daha küçük kapsamlar yapmaya çalışıyorum. Bu, düz sql üzerinden activerecord'un avantajıydı.)

+2

Bu bir hata olduğunu çıkıyor; Bir sonraki Rails3 sürümü için yamalı. –

+0

yup, şu anda sadece 1 kez içerir, böylece sorunu atlatmak istiyorsanız, yeni bir kapsam oluşturun ... hem de içerir ... (: country,: katılımcı) ... oops ... * iç çek * – Ingo

cevap

5

Genel bir kural olarak, istekli yükleme için :includes ve koşullar için :joins kullanın. İkinci kapsamda, bir katılma birleştirmesi gerektiğinden, katılma SQL'in elle yazılması gerekir. sözü

, şunu deneyin:

scope :global_only, lambda { |user| 
    joins(:country). 
    where(["countries.area_id != ?", user.area]) 
} 

scope :not_belonging_to, lambda { |user| 
    joins("left join participants on participants = #{user.id}"). 
    where("participants.id is null") 
} 

Work.global_only(user).not_belonging_to(user)