表格包含以下字段:badge_id,output_id,fulfill,removed,updated_at。对于每个badge_id,不能有两个具有相同output_id的有效记录。但这并不意味着(badge_id,output_id)是一种独特的组合。删除列表示当前行已被删除。基本上删除或更新操作会触发在表中插入具有最新更改的新行。例如,我们有一个这样的记录:
badge_id| output_id| removed| timely | updated_at
1 | 1 | N | Y | 2013-11-26
要删除该记录,我们实际上插入了另一行,现在它读起来像
badge_id| output_id| removed| timely | updated_at
1 | 1 | N | Y | 2013-11-26
1 | 1 | Y | Y | 2013-11-27
由于(badge_id:1,output_id:1)的最新记录已删除列集,因此表示已删除该组合。但我不能有两行相同(badge_id:1,output_id:1),两者都删除为“N”,如:
badge_id| output_id| removed| timely | updated_at
1 | 1 | N | N | 2013-11-26
1 | 1 | N | Y | 2013-11-27
所以每次为某个badge_id添加一个新的output_id时,我都要检查是否有重复。但通常验证来自ActiveModel的(badge_id,output_id)的唯一性在这里不起作用。如何为此编写干净的自定义验证?感谢。
更新
我想我可能错过了一些关键点。可以添加一个记录然后删除,然后重复添加。因此(badge_id,output_id,removed)的组合也不是唯一的。添加新记录时,我们需要检查(badge_id,output_id),最新记录是否已将设置删除为“Y”。
因此可能的答案如
validate_uniqueness_of :badge_id, scope: [:output_id],
conditions: -> { where(removed: "N") }
在条件where子句中,它应该有updated_at desc的顺序,并且第一个已删除:'N'。我如何将这种条件纳入这一行代码?或者有更好的方法来做到这一点?
答案 0 :(得分:1)
您可以执行以下操作:
validates :unique_badge_and_output_ids
然后unique_badge_and_output_ids
可能是:
def unique_badge_and_output_ids
unless Object.find_by_badge_id_and_output_id_and_removed(self.badge_id, self.output_id, self.removed).blank?
self.errors.add "record already exists" # obviously a better error here would be ideal
end
end
答案 1 :(得分:0)
您可以在validates_uniqueness_of上指定SQL条件:
也可以将唯一性约束限制为一组 记录匹配某些条件。在此示例存档文章中 在验证的唯一性时没有考虑到 title属性:
class Article < ActiveRecord::Base validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') } end
所以在你的例子中:
class YourModel < AR::Base
validate_uniqueness_of :badge_id, scope: [:output_id],
conditions: -> { where(removed: "N") }
end
答案 2 :(得分:0)
希望我能正确理解您的用例。
尝试验证removed
的唯一性,并将其范围限定在badge_id
和output_id
列,但仅限于删除的字段为N时:
class Model < ActiveRecord::Base
validates_uniqueness_of :removed,
scope: [:badge_id, :output_id],
conditions: -> { where.not(removed: 'Y') }
end
它有可能发挥作用。