2010-09-20 15 views
15

अभिवादन में संबंध के माध्यम से,छनन बच्चे को एक has_many में वस्तुओं: रेल 3

मैं एक आवेदन जहां Companies और Users एक CompanyMembership मॉडल है, जो सदस्यता के बारे में अतिरिक्त जानकारी शामिल है के माध्यम से एक दूसरे से संबंधित हैं (विशेष रूप से की जरूरत है, उपयोगकर्ता बूलियन मान admin के माध्यम से, कंपनी का एक व्यवस्थापक है या नहीं)। कोड का एक सरल संस्करण:

class CompanyMembership < ActiveRecord::Base 
    belongs_to :company 
    belongs_to :user 
end 

class Company < ActiveRecord::Base 
    has_many :company_memberships 
    has_many :users, :through => :company_memberships 
end 

class User < ActiveRecord::Base 
    has_many :company_memberships 
    has_many :companies, :through => :company_memberships 
end 
बेशक

, यह सरल company.users.all, एट अल के माध्यम से एक कंपनी के सभी सदस्यों को पाने के लिए बनाता है। हालांकि, मैं उस कंपनी के सभी उपयोगकर्ताओं की एक सूची प्राप्त करने की कोशिश कर रहा हूं जो उस कंपनी के व्यवस्थापक हैं (और यह भी जांचने के लिए कि कोई उपयोगकर्ता किसी दिए गए कंपनी का व्यवस्थापक है या नहीं)। मेरा पहला समाधान company.rb में पीछा कर रहा था:

def admins 
    company_memberships.where(:admin => true).collect do |membership| 
    membership.user 
    end 
end 

def is_admin?(user) 
    admins.include? user 
end 

हालांकि यह काम करता है, कुछ (, यह प्रत्येक सदस्यता से अधिक पुनरावृत्ति है, एसक्यूएल हर बार निष्पादित करने का अधिकार या संबंध है कि अधिक चालाक है??) इसके बारे में अक्षम महसूस करता है, और मैं मुझे यकीन नहीं है कि इस बारे में जाने का कोई बेहतर तरीका है (शायद स्कॉप्स या फैंसी नई Relation ऑब्जेक्ट्स का उपयोग करके रेल 3 का उपयोग करता है?)।

प्रक्रिया के सर्वोत्तम तरीके (अधिमानतः रेल 3 सर्वोत्तम प्रथाओं का उपयोग करके) पर कोई सलाह बहुत सराहना की जाएगी!

उत्तर

16

मेरा मानना ​​है कि मैं इस बारे में गलत रास्ते पर जा रहा था, users के बजाय company_memberships पर स्थिति को निर्दिष्ट है, जो क्या मैं वास्तव में चाहता था (Users की एक सूची थी, न कि एक CompanyMemberships की सूची)। समाधान मुझे लगता है कि मैं खोज रहा था है:

users.where(:company_memberships => {:admin => true}) 

जो (1 की आईडी के साथ कंपनी के लिए) निम्नलिखित एसक्यूएल उत्पन्न करता है:

SELECT "users".* FROM "users" 
    INNER JOIN "company_memberships" 
    ON "users".id = "company_memberships".user_id 
    WHERE (("company_memberships".company_id = 1)) 
    AND ("company_memberships"."admin" = 't') 

मुझे यकीन है कि नहीं कर रहा हूँ अभी तक अगर मैं इसे की आवश्यकता होगी

सक्रिय रिकॉर्ड आप अग्रिम में सभी संघों किहैं निर्दिष्ट कर सकते हैं:, लेकिन includes() विधि नीचे एसक्यूएल क्वेरी की संख्या यदि आवश्यक हो रखने के लिए उत्सुक लोड हो रहा है प्रदर्शन करेंगेलोड होने जा रहा है। यह includes Model.find कॉल की विधि निर्दिष्ट करके संभव है। इसमें शामिल हैं, सक्रिय रिकॉर्ड यह सुनिश्चित करता है कि निर्दिष्ट एसोसिएशन query.queries की न्यूनतम संभव संख्या का उपयोग करके लोड किए गए हैं। RoR Guides: ActiveRecord Querying

(मैं अभी भी किसी को जो सोचता है कि यह सबसे अच्छा/सबसे सही प्रभावी/इस बारे में जाने के लिए रास्ता नहीं है से किसी भी सुझाव के लिए खुला रहा हूँ।)

2

कैसे कुछ इस तरह के बारे में:

Company.find(:id).company_memberships.where(:admin => true).joins(:user) 
+1

एक कदम करीब! जबकि यह वह उत्तर नहीं है जिसे मैं ढूंढ रहा था, यह मुझे इसके लिए नेतृत्व किया :) –

7

एक भी क्लीनर तरीका होगा इस तरह से अपनी कंपनी मॉडल, कुछ करने के लिए एक संघ को जोड़ने के लिए:

has_many :admins, :through => :company_memberships, :class_name => :user, :conditions => {:admin => true} 

आप rails doc में खुदाई करने के लिए सटीक सिंटैक्स सही पाने के लिए हो सकता है।

आपको इसकी आवश्यकता नहीं होनी चाहिए: शामिल करें, जब तक कि आपके पास अन्य कक्षाएं हों: उपयोगकर्ता जो आप अपने विचार में संदर्भित कर सकते हैं।