如何validationRuby on Rails中一对id的唯一性?

假设在Ruby中进行以下数据库迁移:

     create_table:question_votes do | t |
       t.integer:user_id
       t.integer:question_id
       t.integer:投票

       t.timestamps
    结束

进一步假设我希望DB中的行包含唯一的(user_id,question_id)对。 为了实现这个目标,什么才是正确的灰尘?

  validates_uniqueness_of:user_id,:question_id 

似乎只是简单地让用户id唯一的行,并通过问题id唯一,而不是唯一的一对。

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

如果需要包含另一列(或更多),则可以将其添加到范围。 例:

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

如果使用mysql,您可以使用唯一索引在数据库中执行此操作。 这是像这样的:

 add_index :question_votes, [:question_id, :user_id], :unique => true 

当您尝试保存question_id / user_id的doubled-up组合时,这将引发exception,因此您必须尝试并找出要捕获和处理的exception。

从RailsGuides 。 validates作品:

 class QuestionVote < ActiveRecord::Base validates :user_id, :uniqueness => { :scope => :question_id } end 

除了编写你自己的validation方法,你可以用validates_uniqueness_of做的最好的是:

 validates_uniqueness_of :user_id, :scope => "question_id" 

这将检查user_id在所有具有与您试图插入的logging相同的question_id的行中是唯一的。

但那不是你想要的

我相信你正在寻找组合:user_id:question_id在整个数据库中是唯一的。

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

  1. 写你自己的validation方法。
  2. 在数据库中创build一个约束,因为您的应用程序仍然有可能会同时处理两条logging。

最好的方法是使用两者,因为唯一性validation通过时,rails不是100%可靠的。

您可以使用:

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

并在安全方面100%,在你的数据库(MySQL前)添加此validation,

  add_index :question_votes, [:user_id, :question_id], unique: true 

然后你可以在你的控制器中使用:

  rescue ActiveRecord::RecordNotUnique 

所以现在你是100%安全的,你将不会有重复的价值:)

当你创build一个新的logging时,这是行不通的,因为你的父模型的id在validation时还不存在。

这应该为你工作。

 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 

在上面的代码中,我得到了所有参数集合的b_id ,然后比较唯一值与获得的b_id之间的长度是否相等。
如果等于意味着没有重复的b_id

注意:不要忘记在数据库的列中添加唯一的