2014-02-12 26 views
1

我有一個關係到一個朋友的模型(的has_many/belongs_to的)測試,如果在加盟的ActiveRecord查詢存在對象

連接後用戶模式,我想能夠檢查是否在存在一定朋友對象已加入用戶的朋友:

users = User.joins(:friends).where("some condition") # subset of total friends 
fs = Friend.all 
fs.each do |f| 
    if users.friends.includes?(f) # match! 
    ... 
    else # no match 
    ... 
end 

代碼原樣不起作用,我在代碼中獲取此功能時遇到困難。

回答

1

嘗試這樣:

users.friends.where(id: u.id).exists? 

這應該產生像這樣的查詢:

SELECT 1 AS one FROM `users` WHERE `users`.`friend_id` = 42 AND `users`.`id` = 1 LIMIT 1 

你要麼拿回數字1(被認爲是 「truthy」),或無(被認爲是「假的」)。

旁註:除非你以後需要使用您的u變量,你也許可以用簡單的where子句中放置some_id直接脫身,而不是做第二次User查找。

編輯

在你的循環,可能會是什麼原因導致你原來的問題只注意到一個問題。當您加載用戶列表時,除非有一個limit子句或調用.first,否則您將獲得一組用戶。所以我猜你的應用程序crapping出在這條線:

users.friends.includes?(f) 

因爲.friendsUser對象的方法,而不是一個數組。

所以你必須做一個嵌套的循環,而不是像這樣:

fs.each do |f| 
    users.each do |u| 
     u.friends.includes?(f) 
    end 
end 

注意,此方法可能會很慢,取決於朋友和用戶數。這是一種非常低效的算法,這就是爲什麼我試圖在評論中更好地理解你的情況的原因,因爲我確信有更高效的方式來完成你的任務。

+0

我不想再次查詢數據庫。關鍵是要檢查已經加入的activerecord集合 – Jason

+0

@Jason用你現在查詢的方式,你在這件事上沒有選擇。請記住,活動記錄關係是延遲加載的。意思是說,你的'用戶'或'u'對象還沒有填充「朋友」列表。只有當你嘗試使用關聯時,它們纔會被加載(導致另一個數據庫調用)。如果你檢查你的日誌,你會注意到一個初始的「用戶」查詢的查詢,然後當你嘗試用'friends集合做什麼時,你會看到另一個查詢。 [第1部分或第2部分] –

+0

@Jason [2的第2部分]我猜你擔心再次觸摸數據庫的性能。如果你喜歡,我可以發佈一個替代品,但如果你願意的話,你不得不在Ruby中迭代一個數組,而不是讓數據庫優化發生。總之,假設你在這些列上有適當的索引,這種情況下的數據庫查找可能比線性數組搜索快得多。 –