验证两列Rails的值的唯一性

时间:2015-07-22 21:34:48

标签: ruby-on-rails validation

emailnew_email是两个不同的列。每封电子邮件都应该是唯一的,因此,如果在任一列中添加了电子邮件,则该邮件在emailnew_email列中都不会存在。

背景故事:我为已激活的帐户创建了主要email,并在用户决定更改其电子邮件地址但尚未通过电子邮件确认验证新电子邮件地址时设置第二个new_email

大多数SO搜索都提供了scope solution

我已经尝试validates :email, uniqueness: {scope: :new_email}validates :new_email, uniqueness: {scope: :email}但是我很确定此功能会在email1, email2对中创建一个新密钥,而这不是预期的效果。

目前,我正在使用以下两个测试用例(失败)来判断我的代码的有效性。

test "new_email should not match old email" do
  @user.new_email = @user.email
  assert_not @user.valid?
end

test "new_email addresses should be unique" do
  duplicate_user = @user.dup
  duplicate_user.new_email = @user.email.upcase
  duplicate_user.email = @user.email + "z"
  @user.save
  assert_not duplicate_user.valid?
end

3 个答案:

答案 0 :(得分:0)

我认为你真的只想写一个自定义验证器,如下所示:

validate :emails_are_unique

def emails_are_unique
  if email == new_email
    errors.add(:base, 'Your new email can not match your old email')
  end
end

哪个会做你想要的。

答案 1 :(得分:0)

范围不会削减它...确实mail在所有可能共享相同new_mail并赢得&#的记录中是唯一的39; t捕获不同new_email值的唯一性,也不比较两列中的值。

使用标准'唯一性'确保列中没有重复。

然后您需要为交叉列创建自定义验证...

validate :emails_unique

def emails_unique
  found_user = User.find_by(new_email: email) 
  errors.add(:email, "email is someone's new email") if found_user
  return unless new_email
  found_user = User.find_by(email: new_email) 
  errors.add(:new_email, "new email is someone's regular email") if found_user
end

答案 2 :(得分:0)

validates :email, uniqueness: {scope: :new_email}将确保emailnew_email具有相同值的所有记录中是唯一的。这不是你想要的。

您必须编写自定义验证功能,例如:

def validate_email_and_new_email_unique
  if email && self.class.exists?("email = :email OR new_email = :email", email: email)
    errors.add :email, "must be unique"
  end
  if new_email && self.class.exists?("email = :email OR new_email = :email", email: new_email)
    errors.add :new_email, "must be unique"
  end
end