2013-06-24 52 views
3

我看到有類似問題的其他線程,但他們似乎並沒有解決我的問題。我正在關注http://ruby.railstutorial.org/上的教程,以獲得基本用戶註冊和登錄或另一個項目,然後是樣本。驗證失敗:密碼摘要不能爲空

基本上,當我運行rspec我不斷收到此錯誤。我已經完成了所有的遷移和測試準備。真的難住這個。

1) User should reject duplicate email addresses 
Failure/Error: User.create!(@attr) 
ActiveRecord::RecordInvalid: 
    Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank 
# ./spec/models/user_spec.rb:60:in `block (2 levels) in <top (required)>' 

2) User should accept valid email addresses 
Failure/Error: valid_email_user.should be_valid end 
    expected #<User id: nil, name: "Example User", email: "[email protected]", created_at: nil, updated_at: nil, password_digest: nil> to be valid, but got errors: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank 
# ./spec/models/user_spec.rb:48:in `block (3 levels) in <top (required)>' 
# ./spec/models/user_spec.rb:46:in `each' 
# ./spec/models/user_spec.rb:46:in `block (2 levels) in <top (required)>' 

3) User should create a new instance given valid attributes 
Failure/Error: User.create!(@attr) 
ActiveRecord::RecordInvalid: 
    Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank 
# ./spec/models/user_spec.rb:25:in `block (2 levels) in <top (required)>' 

4) User should reject email addresses identical up to case 
Failure/Error: User.create!(@attr.merge(:email => upcased_email)) 
ActiveRecord::RecordInvalid: 
    Validation failed: Password digest can't be blank, Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank 
# ./spec/models/user_spec.rb:67:in `block (2 levels) in <top (required)>' 

這裏是我的user_spec

require 'spec_helper' 

describe User do 
    before(:each) do 
    @attr = { :name => "Example User", :email => "[email protected]" } 
    end 

    before do 
    @user = User.new(name: "Example User", email: "[email protected]", 
        password: "foobar", password_confirmation: "foobar") 
    end 

    subject { @user } 

    it { should respond_to(:name) } 
    it { should respond_to(:email) } 
    it { should respond_to(:password_digest) } 
    it { should respond_to(:password) } 
    it { should respond_to(:password_confirmation) } 
    it { should respond_to(:authenticate) } 

    it { should be_valid } 

    it "should create a new instance given valid attributes" do 
    User.create!(@attr) 
    end 

    it "should require a name" do 
    no_name_user = User.new(@attr.merge(:name => "")) 
    no_name_user.should_not be_valid 
    end 

    it "should require an email address" do 
    no_email_user = User.new(@attr.merge(:email => "")) 
    no_email_user.should_not be_valid 
    end 

    it "should reject names that are too long" do 
    long_name = "a" * 51 
    long_name_user = User.new(@attr.merge(:name => long_name)) 
    long_name_user.should_not be_valid 
    end 

    it "should accept valid email addresses" do 
    addresses = %w[[email protected] [email protected] [email protected]] 
    addresses.each do |address| 
     valid_email_user = User.new(@attr.merge(:email => address)) 
     valid_email_user.should be_valid end 
    end 

    it "should reject invalid email addresses" do 
    addresses = %w[[email protected],com user_at_foo.org [email protected]] 
    addresses.each do |address| 
     invalid_email_user = User.new(@attr.merge(:email => address)) 
     invalid_email_user.should_not be_valid end 
    end 

    it "should reject duplicate email addresses" do 
    # Put a user with given email address into the database. 
    User.create!(@attr) 
    user_with_duplicate_email = User.new(@attr) 
    user_with_duplicate_email.should_not be_valid 
    end 

    it "should reject email addresses identical up to case" do 
    upcased_email = @attr[:email].upcase 
    User.create!(@attr.merge(:email => upcased_email)) 
    user_with_duplicate_email = User.new(@attr) 
    user_with_duplicate_email.should_not be_valid 
    end 

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

    describe "when password doesn't match confirmation" do 
    before { @user.password_confirmation = "mismatch" } 
    it { should_not be_valid } 
    end 

    describe "when password confirmation is nil" do 
    before { @user.password_confirmation = nil } 
    it { should_not be_valid } 
    end 

    describe "with a password that's too short" do 
    before { @user.password = @user.password_confirmation = "a" * 5 } 
    it { should be_invalid } 
    end 

    describe "return value of authenticate method" do 
    before { @user.save } 
    let(:found_user) { User.find_by_email(@user.email) } 

    describe "with valid password" do 
     it { should == found_user.authenticate(@user.password) } 
    end 

    describe "with invalid password" do 
     let(:user_for_invalid_password) { found_user.authenticate("invalid") } 

     it { should_not == user_for_invalid_password } 
     specify { user_for_invalid_password.should be_false } 
    end 
    end 

end 

這裏是我的用戶模型

class User < ActiveRecord::Base 

    attr_accessible :name, :email, :password, :password_confirmation 
    has_secure_password 

    before_save { |user| user.email = email.downcase } 

    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, 
      format:  { with: VALID_EMAIL_REGEX }, 
      uniqueness: { case_sensitive: false } 
    validates :password, presence: true, length: { minimum: 6 } 
    validates :password_confirmation, presence: true 
end 

回答

3

在所有的測試失敗,您使用@attr = { :name => "Example User", :email => "[email protected]" }來創建新的用戶。但要創建一個新用戶,您必須設置passwordpassword_confirmation。將這些屬性添加到@attr散列。應該自動設置password_digest字段,並且應該可以保存用戶。

+0

謝謝!我知道這是我的跛腳。 – isea

3

您的驗證太破,密碼和password_confirmation應該如果用戶創建的,但需要此後不

validates :password, presence: true, length: { minimum: 6 } 
validates :password_confirmation, presence: true 

你會遇到的問題,如果你嘗試以後更新的用戶,說改變其名稱,因爲它然後會檢查密碼和password_confirmation,但用戶已經有一組密​​碼,通常存儲在passwordcryptist字段中,通過bcrypt加密,但不會與密碼一起存儲並以純文本形式確認。

我推薦這只是要驗證新的記錄:

validates :password, presence: true, length: { minimum: 6 } if new? 
validates :password_confirmation, presence: true if new? 
+4

不應該在':驗證:密碼,存在:true,長度:{minimum:6} on::create'而不是? – mario

+0

可能只是從我的Sequel模型看起來很急,在AR驗證可能會稍有不同 – jethroo

0

刪除這一行

attr_accessible :name, :email, :password, :password_confirmation 

現在應該工作。

這樣可以防止方法rails方法password =被調用。 (另見secure_password.rb)

+0

雖然這可能會解決問題,包括解釋[真的有幫助](//meta.stackexchange.com/q/114762 )來提高你的帖子的質量。請記住,你正在爲將來的讀者回答這個問題,而不僅僅是現在問的人!請編輯您的答案以添加解釋,並指出適用的限制和假設。 –