是否有一种rail -way方法来验证实际记录是唯一的,而不仅仅是列?例如,一个友谊模型/表不应该有多个相同的记录,比如:

user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20

当前回答

这可以通过对这两列的数据库约束来完成:

Add_index:friends, [:user_id,:friend_id], unique: true

您可以使用rails验证器,但通常我建议使用数据库约束。

更多阅读:https://robots.thoughtbot.com/validation-database-constraint-or-both

其他回答

这可以通过对这两列的数据库约束来完成:

Add_index:friends, [:user_id,:friend_id], unique: true

您可以使用rails验证器,但通常我建议使用数据库约束。

更多阅读:https://robots.thoughtbot.com/validation-database-constraint-or-both

你可以使用validates来验证一列的唯一性:

validates :user_id, uniqueness: {scope: :friend_id}

通过多列验证的语法是相似的,但你应该提供一个字段数组:

validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}

然而,上述验证方法存在竞态条件,不能确保一致性。考虑下面的例子:

数据库表记录被认为是唯一的n个字段; 多个(两个或多个)并发请求,分别由不同的进程(应用程序服务器,后台工作服务器或任何正在使用的进程)处理,访问数据库,在表中插入相同的记录; 每个进程并行验证是否存在具有相同n个字段的记录; 每个请求的验证都成功通过,每个流程在表中创建一个具有相同数据的记录。

为了避免这种行为,应该在db表中添加一个唯一的约束。你可以使用add_index helper为一个(或多个)字段设置它,通过运行以下迁移:

class AddUniqueConstraints < ActiveRecord::Migration
  def change
   add_index :table_name, [:field1, ... , :fieldn], unique: true
  end
end

警告:即使在你设置了唯一的约束之后,两个或多个并发请求也会试图将相同的数据写入db,但这不会创建重复的记录,而是会引发一个ActiveRecord::RecordNotUnique异常,你应该分别处理:

begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end 

您可以按照如下方式确定validates_uniqueness_of调用的范围。

validates_uniqueness_of :user_id, :scope => :friend_id