Rails 3验证一个值对列的唯一性?

时间:2011-08-09 22:55:03

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

我有一个active列的模型,它是一个布尔值。我想验证针对company_id的所有新添加记录的唯一性,这样只要company_id设置为active,我就可以向表中添加任意数量的记录falseactive。每个company_id应该只有一个validates :company_id, :uniqueness => { :scope => :active } 条记录。

我怎么写这个?我已经尝试过了:

active

但是,这似乎也会对false company_id的唯一组合进行验证(这样我在表格中永远不会有两个active {{1} }}状态,无论active是什么) - 上面的验证允许company_id的两个记录,一个记录active = false,另一个记录active = true。一旦这两个记录进入,验证就会阻止其他所有记录。

然后我尝试添加这个:

scope :active, where(:active => true)

但这似乎没有改变验证(与上述相同的问题)。

如何编写此验证,以便只要company_id为false,我就可以添加同一active个记录,并且每active = true只允许一个company_id }?

5 个答案:

答案 0 :(得分:14)

无需使用validates_each - 仅当您想要通过同一个块传递多个属性时才这样做。只需创建自定义验证:

validate :company_id_when_active

def company_id_when_active
  if active? and CompanyTerm.exists? ["company_id = ? AND active = 1 AND id != ?", company_id, id.to_i]
    errors.add( :company_id, 'already has an active term')
  end
end

答案 1 :(得分:7)

Rails 4+为此提供了更好的解决方案。

  validates_uniqueness_of :company_id, conditions: -> { where(active: true) }

结帐documentation

答案 2 :(得分:4)

好的,我想我终于搞清楚了。

检查Rails指南导致我validates_each,这使我得到了这个解决方案:

scope :active, where(:active => true)

validates_each :company do |model, attr, value|
  active = CompanyTerm.active.where(:company_id => value)
  model.errors.add(attr, 'already has an active term') unless active.empty?
end

我不知道这是否是最有效的写作方式,但它有效。我愿意接受任何建议!

答案 3 :(得分:1)

旧主题,但有最简单的解决方案。上面的答案几乎是正确的。您可以使用:if语句作为关键字:

validates :active, :uniqueness => { :scope => :company_id }, :if => :active

答案 4 :(得分:-2)

validates :company_id, :uniqueness => { :scope => :active } unless Proc.new { self.active }

也许你想打电话给公司

validates :company, :uniqueness => { :scope => :active } unless Proc.new { self.active }

修改

基于您的解决方案的答案更有效:

scope :active, where(:active => true)

validates_each :company do |model, attr, value|
  model.errors.add(attr, 'already has an active term') if CompanyTerm.active.exists?(:company_id => value)
end