我有两个表,资产和关系。它们看起来像这样(加上其他我为简洁起见省略的列):
# 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的顺序相反。
如何防止这种情况发生(最好是在数据库级别)?
如果要在数据库级别对其进行验证,则需要在联接表的两个字段上都设置复合索引。可以在这里找到更多信息: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