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

これは、2 人の人物間の会話を見つけようとします。私のコントローラーでは、次のアクションがあります。

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 に答える