2014-02-12 23 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中迭代一个数组,而不是让数据库优化发生。总之,假设你在这些列上有适当的索引,这种情况下的数据库查找可能比线性数组搜索快得多。 –