2013-06-24 50 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 )来提高你的帖子的质量。请记住,你正在为将来的读者回答这个问题,而不仅仅是现在问的人!请编辑您的答案以添加解释,并指出适用的限制和假设。 –