2013-07-30 69 views
6

與rails 4我使用has_secure_password在我的用戶模型中,技巧說如果我不設置:password_confirmation它永遠不會被觸發,但爲什麼當我運行測試時我得到錯誤:確認密碼不能爲空如下所示:rails 4 has_secure_password渲染密碼確認可選

Failures: 

1) User 
Failure/Error: it { should be_valid } 
    expected #<User id: nil, name: "joe", email: "[email protected]", created_at: nil, 
    updated_at: nil, password_digest: "$2a$04$mcRr/msgYQR3kBVc3kv/m.UotBJuJuSXZKMw 
    /eHTvU87..."> to be valid, but got errors: Password confirmation can't be blank 

我的測試文件的樣子:

require 'spec_helper' 

describe User do 

    before { @user = User.new(name: 'joe', email: '[email protected]', password: 'foo') } 

    subject { @user } 
    #.... 
    #.... 
    describe "when password is not present" do 
    before { @user.password = "" } 
    it { should_not be_valid } 
    end 
end 

爲什麼我得到這個錯誤,有作爲解決方案?感謝的

回答

5

更改測試的before行這樣的:

before { @user = User.new(
    name: 'joe', 
    email: '[email protected]', 
    password: 'foo', 
    password_confirmation: 'foo') #<== this line! 
} 

這應該修復它。

這是什麼:

你知道當你在幾乎任何網站上創建一個新帳戶,他們要求你做一個口令,然後輸入兩次?這就是這個。當您創建新用戶時,has_secure_password需要密碼兩次以確保您沒有輸入錯字。

如果password!= password_confirmation,它將拋出一個異常,並且不會創建用戶。

同樣,這僅用於用戶創建。您無需在登錄表單或其他任何地方輸入兩個密碼。 您不必將此字段添加到您的模型或數據庫中。

如果你有一個用戶創建表單,並且你不想有一個password_confirmation字段,那麼你不需要。你可以在你的控制器中設置password_confirmation = password,然後你可以調用save或者其他的東西。

但對於用戶創作,則password_confirmation必須存在。

+0

,但我不會增加password_confirmation到我的應用程序,我只需要輸入密碼一次 – medBo

+0

它僅在用戶創建期間使用。您不必(也不應該)將其添加到您的模型中。這是'has_secure_password'的一個特性。 –

+0

我不明白,請你能解釋更多! (在我的形式中,我認爲字段的密碼,而不是另一個密碼確認) – medBo

21

長話短說

has_secure_password validations: false # This is the key to the solution 
validates :password, presence: true, length: { minimum: 6 } # Or an length you want 

漫長的歷史

  1. docsthe source code說:

    如果您不需要確認驗證,只是不要爲password_confirmation屬性設置任何值,並且驗證不會被觸發。

  2. 但他們也說:

    驗證對創建密碼的存在,密碼 (使用+ password_confirmation +屬性)的確認會自動添加。如果 您希望關閉驗證,請將驗證通過:false作爲 參數。如果需要,您可以手動添加更多驗證。

  3. 項目#1不是一個完整的描述。我們需要關閉所有驗證 並添加我們自己的驗證規則,使其工作如第2點中所述。

我花了一些時間在這裏,並得到了一個教訓:當你困惑時找到源代碼。這似乎是一種痛苦的方式或困難的方式,但有時候這是正確的方式。

+0

presence:true將不起作用驗證:false將刪除存在條件。但是,由於最小長度爲6,因此無關緊要 – shailesh

+1

如果不將它作爲參數發送,則Rails 4會完全忽略確認,因此如果您忘記將'password_confirmation'屬性列入白名單,它將被忽略,並且您的驗證將獲得勝利別說了。小心這個! –

+0

@shailesh'validations:false'只刪除由'has_secure_password'添加的默認驗證。在密碼字段中添加自定義驗證,例如「presence:true」,仍然可以按預期工作。 – mltsy

1

我做這個作爲一項臨時措施,直到我得到的Rails 4.0.13這個程序4.1及以後:

class User < ActiveRecord::Base 
    has_secure_password 
    # Tempfix until Rails 4.1 https://github.com/rails/rails/pull/11107#issuecomment-21850919 
    raise "Get rid of this on Rails 4.1+" if Rails::VERSION::STRING != "4.0.13" 
    before_validation { self.password_confirmation ||= password } 
end 
+0

這是做什麼的,它是否刪除驗證或使密碼確認等於密碼? –

+1

@SurgePedroza後者。如果確認爲零,則會在驗證運行之前爲其分配密碼值。 –