我为模型full_name
中的复合字段contact
创建了自定义验证:
validate :full_name_must_be_unique
def full_name [last_name, first_name, mid_name].
reject { |n| n.blank? }.join(' ') unless first_name.blank?
nil
end
def full_name_must_be_unique
contact = Contact.find_by(first_name: first_name, mid_name: mid_name, last_name: last_name)
errors.add(:full_name, "must be unique") if contact.present?
end
验证适用于使用&#34更新时创建和失败; full_name必须是唯一的"信息。我想这是因为数据库中存在记录,如果我没有更改全名的属性,则验证失败。 如何解决问题? 控制器:
def update
@contact = Contact.find(params[:id])
if @contact.update(contact_params)
redirect_to contacts_path, notice: "Contact updated."
else
render 'edit'
end
end
更新 在@jonnynemonic和@MrYoshiji的帮助下,验证器的最终版本是:
def full_name_must_be_unique
contact = Contact.where(["first_name = ? and mid_name = ? and last_name = ? and id <> ?", first_name, mid_name, last_name, id])
errors.add(:full_name, "must be unique") if contact.present?
end
答案 0 :(得分:0)
我的建议是对全名进行非规范化,然后只需添加validates_uniqueness_of:
迁移:
add_column :contacts, :full_name, :string
型号:
before_validation -> {
self.full_name = [last_name, first_name, mid_name].
reject { |n| n.blank? }.join(' ') unless first_name.blank?
}
validates_uniqueness_of :full_name
答案 1 :(得分:0)
您需要从查询结果中排除当前记录。确保在另一条记录中检测到双重性。
def full_name_must_be_unique
contact = Contact.find_by(first_name: first_name, mid_name: mid_name, last_name: last_name)
contact.each do |c|
if id != contact.id
errors.add(:full_name, "must be unique") if contact.present?
return
end
end
end
你也可以优化你的查询并获得第一个双重性,并确保它的双重性是另一个当前不同的记录。
您还可以在数据库中创建uniq索引作为预防