I have the following scope on my model:
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
this try to find the conversation between two persons, the on my controller I have the following action:
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
And here's my problem:
I have 3 o more user:
Users, A, B, C, D...no conversations between anyone. I create a conversation between user A and User B. The conversation does not exists, so is created, then if User A wants to start a conversation with User C, the model return false, because the conversation does not exists, son my controller need to create a new one, but, instead of that, the controller is open the conversation between user A and User B, but it have to create a new conversation between user A and User C, and open this conversation.
What I'm doing wrong?? I tried on different browsers and clean my cache.
UPDATE:
after create the first conversation, it always show the first conversation. I mean:
First Conversation
Trying to create other conversations between the following users:
The or
method doesn't work the way you think it does. If you look at the underlying selector:
Conversation.where(sender_id: s, recipient_id: r).or(sender_id: r, recipient_id: s).selector
you'll see this:
{
"sender_id" => s,
"recipient_id" => r,
"$or" => [
{
"sender_id" => r,
"recipient_id" => s,
}
]
}
Calling or
on a query doesn't mean "whatever is in the query already or this extra condition", it simply means "and any of these conditions".
The selector you want is:
{
"$or" => [
{ "sender_id" => s, "recipient_id" => r },
{ "sender_id" => r, "recipient_id" => s }
]
}
and that would be built with a single or
call:
or([
{ sender_id: s, recipient_id: r },
{ sender_id: r, recipient_id: s }
])
Presumably the trailing exists?
call in your scope
isn't there in reality. If it is then you're abusing scope
to create a plain old class method and saying def self.between(sender_id, recipient_id)
would be a better idea.