Ruby on rails Rails:验证唯一的友谊关系
我在跟踪 建立一个友谊体系Ruby on rails Rails:验证唯一的友谊关系,ruby-on-rails,ruby,Ruby On Rails,Ruby,我在跟踪 建立一个友谊体系 #Friendship model id | user_id | friend_id 问题是 如何使user\u id和friend\u id的组合唯一? 阻止从用户id=2创建用户id=1,朋友id=2。朋友id=1 我发现这个模型的设计真的很糟糕。我可以对其建模以实际存储两个ID的组合吗?像友谊\u id\u组合=[1,2],然后验证它 为什么你需要这种独特的组合。考虑如果你想获取单个用户的朋友,那么在当前场景中,你可以使用简单的关联找到它。 @user.fri
#Friendship model
id | user_id | friend_id
问题是
user\u id
和friend\u id
的组合唯一?
阻止从用户id=2创建用户id=1,朋友id=2
。朋友id=1
友谊\u id\u组合=[1,2]
,然后验证它为什么你需要这种独特的组合。考虑如果你想获取单个用户的朋友,那么在当前场景中,你可以使用简单的关联找到它。
@user.friends
如果不想添加两个键,则需要启动两个查询以查找相同的详细信息。一个用于您的朋友,另一个用于请求您作为朋友的人。您可以使用以下选项:
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
2019年更新: 修订建议:
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
我强烈建议根据复合用户id
和朋友id
添加DB约束(唯一索引):
CREATE UNIQUE INDEX users_user_id_friend_id_key ON users (user_id, friend_id);
对。你的思路是正确的。也许最简单的解决方案是使用数据库表创建验证,方法是将ID的组合作为唯一的索引
class CreateFriendshipsUnq < ActiveRecord::Migration
def change
add_index :friendships, [:user_id, :friend_id], unique: true
end
end
class CreateFriendsunq
我想这会满足你的需要。因为在大多数情况下,我想获取
@user.friends
,无论是谁创建了关系,(无论是user\u id=@user,还是friends=@user)。我想这会阻止创建两个user\u id=1,friends\u id=2
,而不是user\u id=1,如果self.class.where(user\u id:friend\u id,friend\u id:user\u id)。存在?
?您可以这样做,但也必须检查相反的情况(使用验证)。它可以工作,但会触发两个SQL查询,而不是一个。这取决于你今天偶然发现的,伟大的解决方案!顺便说一句,现在您可以通过使用或将验证转换为单个查询(在Rails 5+中),例如:User.where(User\u-id:friend\u-id,friend\u-id:User\u-id)或(User.where(User\u-id:User\u-id,friend\u-id:friend\u-id))存在?
。另外,对于DB上的双向索引,它看起来是最好的选择。将两者结合起来是IMO的理想方法。这将只验证一个方面,而不是相反的关系