当2列是同一表的外键时,在3列之间具有唯一性

问题描述 投票:0回答:1

我有两个表,资产和关系。它们看起来像这样(加上其他我为简洁起见省略的列):

# Table name: relationships
#
#  id             :uuid             not null, primary key
#  asset1_id      :uuid             not null
#  asset2_id      :uuid             not null
#  type           :string           not null
# Table name: assets
#
#  id             :uuid             not null, primary key
#  type           :string           not null
#  name           :string           not null

我希望两个资产之间的类型关系唯一。例如,假设我的关系类型为membership

Relationship.create!(type: 'membership', asset1_id: '61d58a49-86a9-4d7f-b069-2ed1fa27b387', asset2_id: '1856df48-3193-45de-bef0-122cd9f58d7b')

如果我尝试再次创建该记录,则可以使用validates :type, uniqueness: { scope: [:asset1_id, :asset2_id] }add_index :relationships, [:type, :asset1_id, :asset2_id], unique: true轻松阻止它,但是当我使用这些情况时,以下情况不是被阻止:

Relationship.create!(type: 'membership', asset1_id: '1856df48-3193-45de-bef0-122cd9f58d7b', asset2_id: '61d58a49-86a9-4d7f-b069-2ed1fa27b387')

注意,这与以前的记录相同,只是资产ID的顺序相反。

如何防止这种情况发生(最好是在数据库级别)?

ruby-on-rails ruby postgresql unique-constraint
1个回答
0
投票

如果要在数据库级别对其进行验证,则需要在联接表的两个字段上都设置复合索引。可以在这里找到更多信息:How to implement a unique index on two columns in rails

假设您调用联接表memberships,请尝试以下迁移:

add_index :memberships, [:relationship_id, :asset_id], unique: true

或者,让rails处理验证:

class Membership < ActionRecord::Base
  validates_uniqueness_of :relationship_id, scope: :membership_id
  ...
end

更多有关Rails验证的内容:https://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of

© www.soinside.com 2019 - 2024. All rights reserved.