Ruby on rails 如何在RubyonRails中验证一对ID的唯一性?

Ruby on rails 如何在RubyonRails中验证一对ID的唯一性?,ruby-on-rails,validation,model,unique-constraint,Ruby On Rails,Validation,Model,Unique Constraint,假设在Ruby中进行以下DB迁移: create_table :question_votes do |t| t.integer :user_id t.integer :question_id t.integer :vote t.timestamps end 创建表格:问题投票| t、 整数:用户id t、 整数:问题号 t、 整数:投票 t、 时间戳 结束 进一步假设我希望数据库中的行包含唯一的(user\u id,question\u

假设在Ruby中进行以下DB迁移:

create_table :question_votes do |t| t.integer :user_id t.integer :question_id t.integer :vote t.timestamps end 创建表格:问题投票| t、 整数:用户id t、 整数:问题号 t、 整数:投票 t、 时间戳 结束 进一步假设我希望数据库中的行包含唯一的(user\u id,question\u id)对。在模型中加入什么样的灰尘才能实现这一点

验证:user\u id、:question\u id的唯一性似乎只是让行按用户id唯一,按问题id唯一,而不是按对唯一

validates_uniqueness_of :user_id, :scope => [:question_id]
如果需要包含另一列(或更多列),也可以将其添加到范围中。例如:

validates_uniqueness_of :user_id, :scope => [:question_id, :some_third_column]

除了编写您自己的验证方法外,您最好使用的
验证\u唯一性\u如下:

validates_uniqueness_of :user_id, :scope => "question_id"
这将检查用户id在与您尝试插入的记录具有相同问题id的所有行中是否唯一

但这不是你想要的

我相信您正在寻找数据库中唯一的
:user\u id
:question\u id
组合

在这种情况下,您需要做两件事:

  • 编写自己的验证方法
  • 在数据库中创建约束 因为还有机会 你的应用程序将同时处理两条记录 同时

  • 如果使用mysql,您可以在数据库中使用唯一索引来执行此操作。有点像:

    add_index :question_votes, [:question_id, :user_id], :unique => true
    
    当您试图保存问题id/用户id的双重组合时,这将引发一个异常,因此您必须进行实验并找出要捕获和处理的异常

    来自<代码>验证
    也起作用:

    class QuestionVote < ActiveRecord::Base
      validates :user_id, :uniqueness => { :scope => :question_id }
    end
    
    classquestionvote{:scope=>:question\u id}
    结束
    
    最好的方法是两者兼用,因为当唯一性验证通过时,rails并不是100%可靠的

    您可以使用:

      validates :user_id, uniqueness: { scope: :question_id }
    
    为了100%安全起见,在数据库(MySQL ex)中添加此验证

    然后,您可以使用以下方法在控制器中进行处理:

      rescue ActiveRecord::RecordNotUnique
    

    因此,现在您已经100%安全,不会有重复的值:)

    当您创建新记录时,这不起作用,因为父模型的
    id
    在验证时仍然不存在。

    这应该对你有用。

    B类:ab
    结束
    AB类:ab
    验证后:验证唯一性
    私有的
    def验证唯一性
    b_id=ab.map(&:b_id)
    除非b_id.uniq.length.eql?b_id.length
    错误。添加(:db,消息:“无重复b”)
    结束
    结束
    结束
    
    在上面的代码中,我获得了参数集合的所有
    b_id
    ,然后比较唯一值和获得的b_id之间的长度是否相等。
    如果是相等的,则表示没有重复的
    b_id


    注意:别忘了在数据库的列中添加unique

    如果我验证的唯一性是:user\u id,:scope=>:question\u id验证的唯一性是:question\u id,:scope=>:user\u id够了吗?我没有看到使用
    scope
    验证
    的唯一性与组合唯一性之间的区别。你能举个例子说明它们之间的区别吗?注意:我还没有回到这个项目,所以我没有时间测试下面的答案。如果有人发布了一个答案,这个答案有一个尽可能短的测试来证明一个答案,以及这个测试的输出,我会接受这个答案。谢谢。是的,但是当您只需要一条错误消息时,例外情况没有帮助。值应该在方括号中,而不是大括号中吗?@gwho方括号表示一个数组,一个值序列。大括号表示一个散列,一组键值对。我们这里不指定键,只指定值。我知道现在有点晚了,你可能已经知道了,但这可能会帮助初学者:)哦,这不是范围lambda。如果你喜欢
    验证
    语法:
    验证:用户id,唯一性:{scope:[:问题id]}
    只有当
    用户id和问题id都相同时,验证才会失败吗?这应该是最好的答案,仅验证是不够的!请参阅本文了解详细原因:最佳响应,感谢您提供所需的一切!
    
      add_index :question_votes, [:user_id, :question_id], unique: true
    
      rescue ActiveRecord::RecordNotUnique
    
    class B < ActiveRecord::Base
      has_many :ab
      has_many :a, :through => :ab
    end
    
    class AB < ActiveRecord::Base
      belongs_to :b
      belongs_to :a
    end
    
    class A < ActiveRecord::Base
      has_many :ab
      has_many :b, :through => :ab
    
      after_validation :validate_uniqueness_b
    
      private
      def validate_uniqueness_b
        b_ids = ab.map(&:b_id)
        unless b_ids.uniq.length.eql? b_ids.length
          errors.add(:db, message: "no repeat b's")
        end
      end
    end