按HABTM关联属性查询模型

时间:2016-04-19 03:13:46

标签: ruby-on-rails ruby ruby-on-rails-4 rails-activerecord active-relation

我在两个模型之间有一个HABTM关联,User和Conversation。 我希望能够查询已登录用户的对话(current_user.conversations),并将其传递给另一个用户的ID,并让它返回由两个用户共享的对话,如果有存在。 (额外的好处是让查询创建一个,如果一个不存在。)

关联工作正常,因此我可以通过@user.conversations@conversation.users之类的实例变量访问关联对象,这样我就可以走很长的路并遍历每个会话对象并搜索用户关联在每一个......但必须有一种有效的方法来构建这个查询。 我希望能够做的是current_user.conversations.where(conversation.users.exists?(id: @user_id))或像Conversation.find(users: {id: @user_id AND current_user.id})这样的事情。

我想这里有一个明显的答案,我一直在这里寻找类似的问题,但没有发现任何问题。在查看了Rails API文档后,我想我所寻找的解决方案在某种程度上涉及.includes(),但我无法使其正常工作。

有什么建议吗?感谢。

2 个答案:

答案 0 :(得分:1)

假设您有两个用户@sender@receiver,并且他们之间有一个(或者更多)对话。查询其共享对话的一种可能方法是使用ActiveRecord中的merge函数。 merge将选择它们之间的对话交叉:

@shared_conversations = @sender.conversations.merge(@receiver.conversations)

请注意,结果将是一个集合,而不是单个会话。在SQL中,这将转换为INNER JOIN

如果您想修改此查询以创建对话(如果该对话不存在),则可以使用first_or_create。顾名思义,first_or_create返回集合中的第一个项目。如果集合为空,它将创建一个新对象。您可以传递一个块以进一步控制新创建的对象:

@shared_conversations = @sender.conversations.merge(@receiver.conversations).first_or_create do |conversation|
  conversation.title = "#{@sender.first_name}'s conversation"
end

您可以在Rails文档中找到有关merge的更多详细信息:http://apidock.com/rails/ActiveRecord/SpawnMethods/merge

答案 1 :(得分:0)

尝试     current_user.conversations.includes(:用户)。凡(user.id:current_user.id)