Jason B
Jason B

Reputation: 7465

Find conversation Between Specific Set of User ID's - Mailboxer Rails

The title of my question basically says all, but I was wondering if anyone can help me find a conversation that exists between a specific set of User ID's. Basically, if someone tries to start a conversation with a certain set of users, if a conversation with that exact set of users already exists, I want my app to load that conversation rather than create another one. What is the proper query to do this? I tried looking at the Conversation class: http://rubydoc.info/gems/mailboxer/Conversation. When I run

Conversation.first.participants

I can see the participants in a conversation, but didn't see any way to query for a conversation that contains only a certain set of ID's.

What I want to be able to do is basically something like:

find Conversation where participants are exactly [current_user.id, 3, 5]

and this would match a conversation with participants with ID's [current_user.id, 3, 5] but not a conversation with participants with ID's [current_user.id, 3] or a conversation with participants with ID's [current_user.id, 3, 5, 7].

Upvotes: 2

Views: 1058

Answers (2)

nxxn
nxxn

Reputation: 349

assuming u1 and u2 are messageable objects:

existing_conversation = Conversation.participant(u1).where('conversations.id in (?)', Conversation.participant(u2).collect(&:id))

https://github.com/mailboxer/mailboxer/issues/95#issuecomment-22741452

Upvotes: 1

khaled_gomaa
khaled_gomaa

Reputation: 3412

After referencing Mailboxer Coversation Doc and sql Finding records that have the same relationships and rails query doc

i think this should work

participants_id = [current_user.id, 3, 5]
select('DISTINCT mailboxer_conversations.*').
  where('mailboxer_notifications.type'=> Mailboxer::Message.name).
  order("mailboxer_conversations.updated_at DESC").
  joins(:receipts).where('mailboxer_receipts.receiver_id IN (#{participants_id.join(",")}) AND mailboxer_receipts.receiver_type => #{current_user.class.base_class.to_s})')').group('mailboxer_conversations.id').having('count(1) = #{participants_id.length}')

the first part of the query

participants_id = [current_user.id, 3, 5]
select('DISTINCT mailboxer_conversations.*').
  where('mailboxer_notifications.type'=> Mailboxer::Message.name).
  order("mailboxer_conversations.updated_at DESC").
  joins(:receipts).where('mailboxer_receipts.receiver_id IN (#{participants_id.join(",")} AND mailboxer_receipts.receiver_type => #{current_user.class.base_class.to_s})')

is used by MailBoxer to get if user is participant or not

the second part

.group('mailboxer_conversations.id').having('count(1) = #{participants_id.length}')

is used to group results by conversation id and filters the results not repeated for each participant which means it will only return the one that has relation with all of them.

Upvotes: 1

Related Questions