Reputation: 946
I have a button called conversation when the user click on it, it creates conversation as record in the database. The issue is if there is 3 users userA, userB, and userC,
if userB click on conversation button to message userA, it will create conversation record fine. but then if userC click on conversation button to message userA, the record wont save and i get rollback
conversation controller:
class ConversationsController < ApplicationController
before_action :authenticate_user!
def index
@conversations = Conversation.involving(current_user)
end
def create
if Conversation.between(params[:sender_id], params[:recipient_id]).present?
@conversation = Conversation.between(params[:sender_id], params[:recipient_id]).first
else
@conversation = Conversation.create(conversation_params)
end
redirect_to conversation_messages_path(@conversation)
end
private
def conversation_params
params.permit(:sender_id, :recipient_id)
end
end
the error happens on this line
redirect_to conversation_messages_path(@conversation)
conversation model:
class Conversation < ApplicationRecord
belongs_to :sender, foreign_key: :sender_id, class_name: "User"
belongs_to :recipient, foreign_key: :recipient_id, class_name: "User"
has_many :messages, dependent: :destroy
validates_uniqueness_of :sender_id, :recipient_id
scope :involving, -> (user) {
where("conversations.sender_id = ? OR conversations.recipient_id = ?", user.id, user.id)
}
scope :between, -> (user_A, user_B) {
where("(conversations.sender_id = ? AND conversations.recipient_id = ?) OR (conversations.sender_id = ? AND conversations.recipient_id = ?)", user_A, user_B, user_B, user_A)
}
end
the error happened because of this line
validates_uniqueness_of :sender_id, :recipient_id
Upvotes: 1
Views: 196
Reputation: 36860
Your uniqueness should be scoped, otherwise you're just setting two independent uniquenesses and (in your example) sender can only have one conversation in the entire database and recipient can only have one conversation in the entire database.
The correct way to do it is...
validates :sender_id, uniqueness: { scope: :recipient_id, message: "there is already a converation between these people" }
The scoped
means there can only be one record with this sender for this recipient.
Upvotes: 2