我已经看到其他SO问题,例如 - How do you validate uniqueness of a pair of ids in Ruby on Rails? - 其中描述了添加范围参数以强制实施密钥对的唯一性,即(来自答案)
validates_uniqueness_of :user_id, :scope => [:question_id]
我的问题是你如何对整行数据进行这种验证?
在我的情况下,我有五列,只有全部五列相同才能拒绝数据。该数据不是用户输入的,该表本质上是一个连接表(没有id或时间戳)。
我目前的想法是搜索包含所有列值的记录,并且仅在查询返回nil时才创建,但这似乎是一个糟糕的工作。有没有更简单的“轨道方式”来做到这一点?
答案 0 :(得分:2)
您需要创建自定义验证器(http://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations):
class TotallyUniqueValidator < ActiveModel::Validator
def validate(record)
if record.attributes_for_uniqueness.values.uniq.size == 1
record.errors[:base] << 'All fields must be unique!'
end
end
end
class User
validates_with TotallyUniqueValidator
def attributes_for_uniqueness
attributes.except :created_at, :updated_at, :id
end
end
这里重要的一点是:
if record.attributes_for_uniqueness.values.uniq.size == 1
这将获取您要检查唯一性的所有属性的哈希值(在这种情况下除了id和timestamps之外的所有内容)并将其转换为仅包含值的数组,然后在其上调用uniq,仅返回uniq值和如果大小为1那么它们都是相同的值。
根据您的表没有ID或时间戳的评论更新:
然后你可以简单地做:
if record.attributes.except(:id).values.uniq.size == 1
...因为我非常确定它仍有id,除非您确定它不会删除except
部分。
答案 1 :(得分:0)
您可以在迁移中向表中添加唯一索引:
add_index :widgets, [:column1, :column2, :column3, :column4, :column5], unique: true
结果索引将要求5列的每个组合必须是唯一的。