Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails:验证唯一的友谊关系_Ruby On Rails_Ruby - Fatal编程技术网

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

  • 我发现这个模型的设计真的很糟糕。我可以对其建模以实际存储两个ID的组合吗?像
    友谊\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的理想方法。这将只验证一个方面,而不是相反的关系