I'm following http://railscasts.com/episodes/163-self-referential-association to make a friendship system.
#Friendship model
id | user_id | friend_id
The problem is
How can I make the combination of user_id
and friend_id
unique? prevent creating user_id = 1, friend_id = 2
from user_id = 2. friend_id = 1
I find this model design is really bad. Can I model it to actually store the combine of 2 ids? Like friendship_id_combination = [1, 2]
, and then validate it.
You can use the following:
validate :users_are_not_already_friends
def users_are_not_already_friends
combinations = ["user_id = #{user_id} AND friend_id = #{friend_id}",
"user_id = #{friend_id} AND friend_id = #{user_id}"]
if User.where(combinations.join(' OR ')).exists?
self.errors.add(:user_id, 'Already friends!')
end
end
Update 2019:
Revised suggestion:
def users_are_not_already_friends
if User.where(user_id: friend_id, friend_id: user_id).exist?
|| User.where(user_id: user_id, friend_id: friend_id).exist?
self.errors.add(:user_id, 'Already friends!')
end
end
And I would strongly advise to add a DB constraint (unique index) based on the composite user_id
and friend_id
:
CREATE UNIQUE INDEX users_user_id_friend_id_key ON users (user_id, friend_id);
Why you need this unique combination. Consider if you want to fetch friends of single user then in current scenario you can find it using simple association.
@user.friends
And if you don't want to add two keys then you need to fire two queries to find same details. One for your friends and other for who requested you as a friend.
Yes. You are thinking along the right path. Perhaps the simplest solution is to use the database table to create the validation by making the combination of IDs a unique index.
class CreateFriendshipsUnq < ActiveRecord::Migration
def change
add_index :friendships, [:user_id, :friend_id], unique: true
end
end
I think this will do what you want.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.