2

这是检查电子邮件唯一性的 rspec 测试(来自http://ruby.railstutorial.org/chapters/modeling-users.html#code-validates_uniqueness_of_email_test

require 'spec_helper'

describe User do

  before do
    @user = User.new(name: "Example User", email: "user@example.com")
  end
  .
  .
  .
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
end

正如作者提到的,我补充说

class User < ActiveRecord::Base
  .
  .
  .
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end

到我的用户模型并且测试通过。

但是@user 还没有保存到数据库中(我在代码的任何地方都找不到@user.save 语句。)所以,user_with_same_email 已经是唯一的,因为数据库中没有其他用户使用相同的电子邮件。那么它是如何工作的呢?

我在控制台中创建了类似的东西。user_with_same_email.valid?返回 false (错误“已被采取”),但 user_with_same_email.save 仍然有效。为什么?

4

2 回答 2

4

您可以使用shoulda-matchers gem。

# spec/models/user_spec.rb
require 'spec_helper'

describe User, 'validations' do
  it { should validate_uniqueness_of(:email) }
  it { should validate_presence_of(:email) }
  it { should validate_format_of(:email).with_message(VALID_EMAIL_REGEX) }
end

对最后一个并不积极,但看起来它应该可以工作。

如果您正在使用许可,您可以在此处使用内置email_validator功能PR

# app/models/user.rb
validates :email, presence: true, email: true
于 2013-05-20T19:46:06.330 回答
2

这是匹配器的源代码be_valid

match do |actual|
  actual.valid?
end

如您所见,匹配器实际上并没有保存记录,它只是调用valid?实例上的方法。valid?检查验证是否通过,如果没有,则在实例上设置错误消息。

在上述情况下,您首先(成功地)保存了具有相同电子邮件 ( ) 的用户,这是因为实际上尚未保存user_with_same_email具有该电子邮件的用户。然后,您正在检查另一个具有相同电子邮件的用户实例 ( ) 上的验证错误,即使您实际上没有保存重复记录,这显然也会失败。@user

关于您在控制台中获得的内容,save即使失败也可能不会返回错误。尝试save!改用。

于 2012-10-02T01:57:12.937 回答