验证多列的唯一性

时间:2011-02-02 05:05:32

标签: ruby-on-rails ruby-on-rails-3 validation activerecord rails-activerecord

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

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

3 个答案:

答案 0 :(得分:313)

您可以按如下方式调整validates_uniqueness_of电话的范围。

validates_uniqueness_of :user_id, :scope => :friend_id

答案 1 :(得分:127)

您可以使用jquery-serialize-object在一列上验证uniqueness

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

多列验证的语法类似,但您应该提供一个字段数组:

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

然而,上面显示的验证方法具有竞争条件,无法确保一致性。请考虑以下示例:

  1. 数据库表记录应该由 n 字段唯一;

  2. 多个(两个或更多)并发请求,由每个单独的进程(应用程序服务器,后台工作服务器或您正在使用的任何)处理,访问数据库在表中插入相同的记录;

  3. 并行验证每个进程是否存在具有相同 n 字段的记录;

  4. 成功传递每个请求的验证,每个进程在表中创建一条具有相同数据的记录。

  5. 要避免这种行为,应该在db表中添加唯一约束。您可以通过运行以下迁移,为一个(或多个)字段设置validates帮助程序:

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

    警告:即使你设置了一个唯一约束,两个或多个并发请求也会尝试将相同的数据写入db,但这不会创建重复的记录, add_index异常,您应该单独处理:

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

答案 2 :(得分:1)

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

if let cell = self.tableView.cellForRow(at: indexpath) as? UITableViewCell { let intersection = cell.frame.intersection(visibleRect) debugPrint(intersection.size.height) }

您可以使用rails验证器,但一般情况下我建议使用数据库约束。

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