Ruby on rails 如何确保不通过activerecords将重复行添加到数据库表中?

Ruby on rails 如何确保不通过activerecords将重复行添加到数据库表中?,ruby-on-rails,postgresql,activerecord,ruby-on-rails-4,model,Ruby On Rails,Postgresql,Activerecord,Ruby On Rails 4,Model,所以我有一张叫做选票的桌子 共有三列。VoterID,VoteforID和Vote 每个列的唯一性并不重要,但是同一行不能重复两次 比如说。这是正确的 投票人|投票人|投票人|投票 1 | 2 | 1 1 | 3 | 1 1 | 4 | 1 2 | 1 | 2 这是错误的 投票人|投票人|投票人|投票 1 | 2 | 1 1 | 2 | 1 1 | 4 | 1 2 | 1 | 2 目前,我正在添加记录之前执行select语句,以确保不存在相同的行。当然,有更好的解决办法 谢谢。使用上的范围参数,

所以我有一张叫做选票的桌子

共有三列。VoterID,VoteforID和Vote

每个列的唯一性并不重要,但是同一行不能重复两次

比如说。这是正确的

投票人|投票人|投票人|投票

1 | 2 | 1

1 | 3 | 1

1 | 4 | 1

2 | 1 | 2

这是错误的

投票人|投票人|投票人|投票

1 | 2 | 1

1 | 2 | 1

1 | 4 | 1

2 | 1 | 2

目前,我正在添加记录之前执行select语句,以确保不存在相同的行。当然,有更好的解决办法


谢谢。

使用上的
范围
参数,例如:

validates :voter_id, uniqueness: { scope: :votefor_id }
作用域参数可以不止一个:

validates :voter_id, uniqueness: { scope: [:votefor_id, :vote] }
更新:(应用程序验证Vs数据库约束) 这真的取决于细节,但对于手头的案例,我个人认为db约束在这里有点过分了,因为发生竞争条件()的可能性很低,因为我们需要

如果我可以假设关于OP业务逻辑的某些东西,
voter
通常是一个登录用户,这意味着重复条目只能来自他

结论: 我有相当多的rails应用程序在生产环境中运行,使用的是
university\u validation
很好,只是在一个列上同时有许多条目进行唯一性检查时失败了(显然我需要db约束)


如果数据完整性非常重要,那么您一定要使用db约束

或者,如果您不介意开销&特别是如果您可以从(voter_id、votefor_id和vote)上的新索引中获益,以提高搜索速度,我会说使用db约束


否则,我会说:保持简单,使用
uniquess\u valdation

使用
scope
参数,例如:

validates :voter_id, uniqueness: { scope: :votefor_id }
作用域参数可以不止一个:

validates :voter_id, uniqueness: { scope: [:votefor_id, :vote] }
更新:(应用程序验证Vs数据库约束) 这真的取决于细节,但对于手头的案例,我个人认为db约束在这里有点过分了,因为发生竞争条件()的可能性很低,因为我们需要

如果我可以假设关于OP业务逻辑的某些东西,
voter
通常是一个登录用户,这意味着重复条目只能来自他

结论: 我有相当多的rails应用程序在生产环境中运行,使用的是
university\u validation
很好,只是在一个列上同时有许多条目进行唯一性检查时失败了(显然我需要db约束)


如果数据完整性非常重要,那么您一定要使用db约束

或者,如果您不介意开销&特别是如果您可以从(voter_id、votefor_id和vote)上的新索引中获益,以提高搜索速度,我会说使用db约束


否则,我会说:保持简单,在表定义中添加一个
唯一的
表约束:

CREATE TABLE votes (
  voter_id   int NOT NULL,
  votefor_id int NOT NULL,
  vote       int NOT NULL,
  UNIQUE (voter_id, votefor_id, vote)
);

这样,PostgreSQL将检查重复项。如果尝试插入一条记录,其所有三列的值都与现有记录中的值相同,则将抛出一个错误。

在表定义中,添加一个
唯一的
表约束:

CREATE TABLE votes (
  voter_id   int NOT NULL,
  votefor_id int NOT NULL,
  vote       int NOT NULL,
  UNIQUE (voter_id, votefor_id, vote)
);

这样,PostgreSQL将检查重复项。如果您尝试插入一条记录,其所有三列的值都与现有记录中的值相同,则会抛出错误。

如果数据完整性至关重要,则不应使用验证来保证唯一性。它可能会失败。保证唯一性的唯一方法是使用数据库约束。这是因为Rails
验证_唯一性
可以有竞争条件

创建迁移以添加索引,或更改现有迁移以反映此更改:

对于新表:

class CreateVotes < ActiveRecord::Migration
  def change
    create_table :votes do |t|
      t.belongs_to :voter
      t.belongs_to :votefor
      t.string :vote # Choose the correct column type
      t.timestamps
    end
    add_index :votes, [:voter_id, :votefor_id, :vote], unique: true
  end
end

如果数据完整性至关重要,则不应使用验证来保证唯一性。它可能会失败。保证唯一性的唯一方法是使用数据库约束。这是因为Rails
验证_唯一性
可以有竞争条件

创建迁移以添加索引,或更改现有迁移以反映此更改:

对于新表:

class CreateVotes < ActiveRecord::Migration
  def change
    create_table :votes do |t|
      t.belongs_to :voter
      t.belongs_to :votefor
      t.string :vote # Choose the correct column type
      t.timestamps
    end
    add_index :votes, [:voter_id, :votefor_id, :vote], unique: true
  end
end

谢谢Nimir,那么验证:投票者id,唯一性:{scope:[:votefor_id,:vote]}和验证:votefor_id,唯一性:{scope:[:voter_id,:vote]}之间的区别是什么呢?再次感谢!这个答案是不正确的。它不能保证唯一性。您需要一个数据库约束。关于您的查询@user3649729,
scope
中的参数定义了应与
voter\u id
一起比较uniquencessThank Nimir的哪些列,那么:validates:voter\u id,university:{scope:[:votefor\u id,:vote]}和validates:votefor\u id,university:{scope:[:voter\u id,:vote]}。再次感谢!这个答案不正确。它不能保证唯一性。您需要一个数据库约束。关于您的查询@user3649729,
scope
中的参数定义了应与
voter\u id
进行唯一性比较的列
否则,一个人可以投票两次(使用不同的投票值)并且:{voter\u id,votefor\u id}不应为空。@wildplasser:可能可以进行多次投票?OP意味着这一点。添加了