2010-09-20 94 views
15

問候關係,過濾孩子在的has_many對象:通過對Rails 3個

我有一個應用程序,CompaniesUsers需要通過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 

雖然這個作品,有什麼感覺低效它(它遍歷每個成員,每次執行SQL,正確的還是關係更聰明?)和我我不確定是否有更好的方法可以解決這個問題(也許使用示波器或Rails 3使用的新對象?)。

任何有關最佳處理方式(最好使用Rails 3最佳實踐)的建議將不勝感激!

回答

16

我相信我會對此錯誤的方式,對company_memberships指定條件,而不是users,這是我其實是想(的Users一個列表,而不是列表CompanyMemberships)。我覺得我一直在尋找解決的辦法是:

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

產生下面的SQL(爲公司ID爲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()方法進行預先加載,儘量減少SQL查詢的必要時數:

活動記錄,您可以在 提前指定所有那些協會將被加載。這是可能的 通過指定includes方法 調用Model.find。使用包含, 活動記錄可確保使用盡可能少的 queries.queries將所有 指定的關聯加載爲 。 RoR Guides: ActiveRecord Querying

(我仍然開放給任何人誰認爲這是不是最好的/最有效/正確的方式去了解這個任何建議。)

2

怎麼是這樣的:

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

更靠近!雖然這不是我正在尋找的答案,但它讓我感到它:) – 2010-09-21 14:47:37

7

一個更清潔的方式將一個協會添加到您的公司的模式,這樣的事情:

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

您可能需要挖掘到rails doc得到確切的語法正確。

您不應該需要:include,除非您的其他類與您可能在視圖中引用的用戶相關聯。