Reputation: 2343
I'm about to build a messaging feature for a rails app.
I thought about having conversations
, conversation_participants
and conversation_messages
.
Which means:
Conversation:
has_many :conversation_participants
has_many :conversation_messages, through: :conversation_participants
Conversation Participant:
belongs_to :conversation
belongs_to :user
has_many :conversation_messages
Conversation Message:
belongs_to :conversation_participant
So far, so good.
I'm just stuck in some scenarios:
Hope somebody could help me out on this one! Thank you!
Upvotes: 1
Views: 1358
Reputation: 1506
You may want to look more into the merge and where methods.
The first example would look something like:
Conversation.joins(:conversation_participants).merge(User.where(:id => user1_id)).merge(User.where(:id => user2_id))
Each merge()
filters the results. You wouldn't want to use merge(User.where(:id => [user1_id, user2_id]))
because you would get all the conversations for both users, not just the common ones.
The second example would be similar to the first one.
In the third example you could add something like .merge(User.where.not(:id => user6_id)
at the end of the query to not include conversations with User 6.
UPDATE
To chain multiple merge
dynamically you could try something like:
conversations = Conversation.joins(:conversation_participants)
user_ids.each{|uid| conversations.merge!(User.where(:id => uid))}
Upvotes: 1
Reputation: 646
It sounds like you will want to set up an association between users and conversations through conversation participants.
How do I find the conversation for User 1 and User 2?
This doesn't seem to be a unique conversation given the way you've set things up. Users 1 and 2 could be in one conversation with only each other, and another conversation that includes other participants. That being said, if you join the conversation_participants table to itself on conversation_id you should be able to find the matches. There are other ways to go about this to and I'm happy to provide more info. The way you decide to approach this will factor into the answers to your other questions as well.
UPDATE:
The query would look something like this:
SELECT cp1.conversation_id
FROM conversation_participants as cp1
JOIN conversation_participants as cp2 ON cp1.conversation_id = cp2.conversation_id
WHERE cp1.participant_id = 1 and cp2.participant_id =2;
Upvotes: 0
Reputation: 322
You can exclude converstion_messages. These are irrelevant, and need to include users.
#user
has_many :conversations, through: converstion_participants
user_12_conv_ids = user_1.conversation_ids & user_2.conversation_ids
user_123_conv_ids = user_12_conv_ids & user_3.conversation_ids
user_123_conversations = Conversation.where(id: user_123_conv_ids)
Now you can select conversations that include only 1, 2, and 3 (as user_ids)
conversations.select{|c| c.user_ids == user_ids}
Upvotes: 1