Rails:验证忽略某些记录的唯一性

时间:2014-01-03 00:58:14

标签: ruby-on-rails

我们正在使用Ruby on Rails 4。

我的“事件”模型有:

  • “title”字段,可以是任意字符串
  • 一个convention_id字段,它是Convention表的索引
  • 状态字段,可以是“建议”,“讨论”,“接受”,“拒绝”或“丢弃”。

我想创建一个验证语句,确保标题在约定中是唯一的。这很容易。

validates :title, :uniqueness => { :scope => :convention_id }

完成我想要的大部分工作。但我想忽略任何状态为“已拒绝”或“已删除”的记录。我真正想要的是向SQL RAILs添加一些WHERE子句,但我不确定如何。

感谢您的帮助。

3 个答案:

答案 0 :(得分:6)

我找到了答案。以下似乎可以正常运作:

validates_uniqueness_of :title,  
  scope: :convention,  
  conditions: -> { where.not(status: ['Dropped', 'Rejected']) }

生成的SQL是

SELECT 1 AS one FROM "events"
  WHERE ("events"."title" = 'Panel' AND 
         "events"."id" != 2 AND 
         "events"."convention_id" = 1) AND
        ("events"."status" NOT IN ('Dropped', 'Rejected'))
  LIMIT 1

我认为这正是我想要的。

再次感谢您的帮助。

答案 1 :(得分:2)

Per the canonical guides,您可以传递Proc并排除条件:

validates :title, 
  uniqueness: {scope: :convention_id},
  unless: Proc.new { |event| event.status == "Rejected" || event.status == "Dropped" }

请注意,哈希火箭(=>)的使用必须一致。在上面的例子中,我用JSON样式表示法替换了哈希火箭语法(Rails 4的事实上),但是可以重写整个语句以使用哈希火箭,如下所示:

validates :title, 
  :uniqueness => {:scope => :convention_id},
  :unless => Proc.new { |event| event.status == "Rejected" || event.status == "Dropped" }

答案 2 :(得分:0)

根据rubocop使用validates创建验证的另一种方法是

validates :title,
          uniqueness: { scope: :convention, conditions: -> { where.not(status: ['Dropped', 'Rejected']) }