2011-03-21 16 views
8

Raylar: Birden fazla koşulla katılın

class Interest < ActiveRecord::Base 
    has_and_belongs_to_many :user_profiles 
end 

class UserProfile < ActiveRecord::Base 
    has_and_belongs_to_many :interests 
end 
gibi basit bir modelim var. Tüm kullanıcıları belirli bir ilgi alanıyla sorgulamak istediğimde bu oldukça basittir

UserProfile.joins(:interests).where('interests.id = ?', an_interest) 

Ama nasıl birden fazla menfaat sahibi olan kullanıcılara bakabilirim? Tabii ki

UserProfile.joins(:interests).where('interests.id = ?', an_interest).where('interests.id = ?', another_interest) 

yaparsam, her zaman boş bir sonuç alırım, çünkü birleşimden sonra, hiçbir satırda aynı anda interest.id = an_interest ve interest.id = another_interest olabilir.

ActiveRecord içinde bir yol var "Ben 2 (belirtilen) çıkarları ile ilişkili kullanıcıların listesini istiyorum?

güncelleme (çözüm) Bu ilk çalışma sürümü geldi, Ömer için kudos Qureshi

 specified_interests.each_with_index do |i, idx| 
     main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id" 
     join_clause = sanitize_sql_array ["inner join interests_user_profiles interests_#{idx} on 
        (#{main_join_clause} and interests_#{idx}.interest_id = ?)", i] 

     relation = relation.joins(join_clause) 
    end 

cevap

4

hiçbir iyidir - bu ifadenin benzeri bir ameliyathane bulunuyor yapmanız gerekenleri

birden dışarı yazılı longhanded birleştirmeler var olan

(?)
profiles = UserProfile 
interest_ids.each_with_index do |i, idx| 
    main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id" 
    join_clause = sanitize_sql_array ["inner join interests interests_#{idx} on 
         (#{main_join_clause} and interests_#{idx}.id = ?)", i] 
    profiles = profiles.join(join_clause) 
end 
profiles 

Gereksinimlerinize uygun olarak main_join_clause değiştirmeniz gerekebilir.

+0

Bu umduğum gibi çok daha karmaşık! Ama kesinlikle beni doğru yöne işaret ettin. Teşekkürler. Tek fark, yazdığınız gibi “içsel ilgi alanları” yerine “iç ilgi alanları” nı içermek zorunda kaldım. –

+0

... ve aynı zamanda "çıkarlar _ # {idx} .id =?" Ile değiştirin. # _ {Idx} .interest_id =? ' –

+0

ah sağ - M-to-M birleşimiydi? Bu mantıklı olurdu, üzgünüm o kadarını okumamıştı! : D –

2

Bu yöntem, belirtilen çıkarlarının en az birine sahip kullanıcıların alacak.

UserProfile.joins(:interests).where(:id => [an_interest_id, another_interest_id]) 

ge için Belirtilen çıkarlar ikisine de sahip t kullanıcıları muhtemelen böyle bir şey yapmak istiyorum:

def self.all_with_interests(interest_1, interest_2) 
    users_1 = UserProfile.where("interests.id = ?", interest_1.id) 
    users_2 = UserProfile.where("interests.id = ?", interest_2.id) 

    users_1 & users_2 
end 

Değil inanılmaz verimli, ama ne gerek yapmalıdır?

+0

UserProfile.joins (: interest) .where ("interests.id =?", [25, 26]) 'yi denedim ama çalışmadı –

+0

Hayır, hala çalışmıyor. "SELECT" user_profiles sorgusunda bir sözdizimi hatası alıyorum. * FROM "user_profiles" INNER JOIN "interest_user_profiles" ON "interests_user_profiles". "User_profile_id" = "user_profiles". "Id" INNER JOIN "interest" ON "interest". "id" = "interest_user_profiles". "interest_id" WHERE (interests.id = 25,26) ' –

+0

Başka bir yanıt hakkındaki yorumunuzu okudum - Mantıksal bir İhtiyaç duyduğunuzu farketmedim. Cevabım bir OR yapacak. – Ant

0

IN (?) ve bir dizi deneyin:

UserProfile.joins(:interests).where('interests.id IN (?)', [1,2,3,4,5]) 
yılında
+1

cevabını güncelledim mantıksal bir OR yapar (bir ilgi ya da diğeri ya da her ikisi de) ... Mantıksal VE İhtiyacım var (tüm ilgi alanları vardır) –

İlgili konular