这是检查电子邮件唯一性的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(错误&#34;已经采取&#34;),但user_with_same_email.save仍然有效。为什么呢?
答案 0 :(得分:2)
以下是be_valid
匹配器的source code:
match do |actual|
actual.valid?
end
如您所见,匹配器实际上并不保存记录,只是在实例上调用方法valid?
。 valid?
检查验证是否通过,如果没有,则在实例上设置错误消息。
在上面的案例中,您首先(成功)使用相同的电子邮件(user_with_same_email
)保存用户,这是有效的,因为该电子邮件的用户实际上还没有已保存。然后,您正在检查具有相同电子邮件的另一个用户实例(@user
)上的验证错误,即使您实际上没有保存重复记录,这显然也会失败。
关于您在控制台中获得的内容,问题可能是save
即使失败也不会返回错误。请尝试使用save!
。
答案 1 :(得分:2)
您可以使用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 here
# app/models/user.rb
validates :email, presence: true, email: true