0

我的模型有以下范围:

scope :between, -> (sender_id,recipient_id) do
    where(sender_id: sender_id, recipient_id: recipient_id).or(sender_id: recipient_id, recipient_id: sender_id).exists?
  end

这试图找到两个人之间的对话,在我的控制器上我有以下操作:

def create
    if Conversation.between(params[:sender_id],params[:recipient_id]).exists?
      @conversation = Conversation.between(params[:sender_id],params[:recipient_id]).first
      redirect_to dashboard_conversation_path(@conversation.id)
    else
      @conversation = Conversation.create!(conversation_params)
      redirect_to dashboard_conversation_path(@conversation.id)
    end
  end

这是我的问题:

我有 3 个以上的用户:

用户,A,B,C,D……任何人之间没有对话。我创建了用户A和用户B之间的对话。对话不存在,所以创建,然后如果用户A想与用户C开始对话,模型返回false,因为对话不存在,儿子我的控制器需要创建一个新的,但是,控制器打开了用户 A 和用户 B 之间的对话,但它必须在用户 A 和用户 C 之间创建一个新的对话,并打开这个对话。

我做错了什么??我尝试了不同的浏览器并清理了我的缓存。


更新:

创建第一个对话后,它总是显示第一个对话。我是说:

第一次对话

  • 用户 A - 用户 B

尝试在以下用户之间创建其他对话:

  • 用户 A - 用户 C,显示对话用户 A、B
  • 用户 C - 用户 B,显示对话用户 A、B
  • 用户 C - 用户 D,显示对话用户 A、B
4

1 回答 1

2

or方法并不像您认为的那样起作用。如果您查看底层选择器:

Conversation.where(sender_id: s, recipient_id: r).or(sender_id: r, recipient_id: s).selector

你会看到这个:

{
  "sender_id" => s,
  "recipient_id" => r,
  "$or" => [
    {
      "sender_id" => r,
      "recipient_id" => s,
    }
  ]
}

调用or查询并不意味着“查询中已有的内容这个额外的条件”,它只是意味着“以及这些条件中的任何一个”。

您想要的选择器是:

{
  "$or" => [
    { "sender_id" => s, "recipient_id" => r },
    { "sender_id" => r, "recipient_id" => s }
  ]
}

这将通过一次or调用来构建:

or([
  { sender_id: s, recipient_id: r },
  { sender_id: r, recipient_id: s }
])

大概你的尾随exists?电话scope实际上并不存在。如果是这样,那么您正在滥用scope创建一个普通的旧类方法,并说def self.between(sender_id, recipient_id)这将是一个更好的主意。

于 2015-06-30T02:07:19.500 回答