2012-10-02 27 views
1

這裏是RSpec的測試,以檢查電子郵件的唯一性(從http://ruby.railstutorial.org/chapters/modeling-users.html#code-validates_uniqueness_of_email_testRspec的測試檢查獨特

require 'spec_helper' 

describe User do 

    before do 
    @user = User.new(name: "Example User", email: "[email protected]") 
    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仍然有效。爲什麼?

回答

2

這裏的source codebe_valid匹配:

match do |actual| 
    actual.valid? 
end 

正如你所看到的,匹配實際上並沒有保存記錄,它只是調用實例上的方法valid?valid?檢查驗證是否會通過,如果沒有,則在實例上設置錯誤消息。

在上述情況下,你是第一個(成功)保存同一個電子郵件(user_with_same_email),其工作方式,因爲與電子郵件地址的用戶實際上已經保存尚未用戶。然後,您正在檢查具有相同電子郵件的另一個用戶實例(@user)上的驗證錯誤,即使您沒有實際保存重複記錄,該錯誤也顯然會失敗。

關於在控制檯中獲得的內容,問題很可能是save即使失敗也不會返回錯誤。改用save!來代替。

+0

哦,我明白了。我認爲這是另一回事。現在這一切都有道理。謝謝:) – TradeRaider

+0

不客氣,很高興答案幫助。 –

1

您可以使用shoulda-matchers寶石。

# 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