Rails: Include all of model A and only a subset of related model B
我试图更好地理解Rails数据库API。如果我具有以下型号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Link has_many :votes belongs_to :user end class Vote belongs_to: link belongs_to :user end class User has_many :links has_many :votes end |
我想"急切地"返回所有链接的列表,并且对于每个链接,我希望user_id等于当前用户的投票。我尝试了这个:
1 | l = Link.all(:include => :votes, :conditions => { :votes => { :user_id => current_user.id}}) |
但这只会返回用户已提交投票的链接列表。我希望它返回所有链接,然后仅返回该用户的投票(如果没有,则不返回)。如何使用include语句执行此操作?
我不得不重复阅读几次这个问题,所以如果对此感到困惑,请告诉我。听起来您想使用
1 2 3 4 | Link.all(:include => :votes, :select=>"DISTINCT links.*", :joins =>"LEFT OUTER JOIN votes ON links.id = votes.link_id AND votes.user_id = #{current_user.id}", :conditions=>"NOT EXISTS (SELECT * FROM votes WHERE votes.link_id = links.id) OR votes.user_id = #{current_user.id}") |
此外,由于您已经在使用Rails 3.2,因此您可能希望使用较新的活动记录查询方法,因为我相信基于旧哈希的finder方法已在Rails 4中弃用。因此,相同的查询看起来像这:
1 2 3 4 | Link.include(:votes) .joins("LEFT OUTER JOIN votes ON links.id = votes.link_id AND votes.user_id = #{current_user.id}") .where("NOT EXISTS (SELECT * FROM votes WHERE votes.link_id = links.id) OR votes.user_id = #{current_user.id}") .uniq.load |
关于条件/ where部分,这将创建一个依赖子查询,如果
更新
如评论中所述,此方法的问题在于相关联的
如果我们抛弃
我能想到的唯一解决方案是在调用关联方法时正确量化您要查找的内容。像这样的东西:
1 | link.votes.where(:user_id=>current_user.id) |
这将产生如下查询:
1 | SELECT votes.* FROM votes WHERE votes.link_id = [the link ID] AND user_id = [the user ID] |
如果有人有更好的解决方案,我将很感兴趣。
希望有帮助。