RoR教程(第10.4章) - 管理属性测试失败

时间:2012-01-23 12:42:23

标签: ruby-on-rails-3.1 rspec railstutorial.org

我是一名RoR-Learner,我选择了迈克尔·哈特尔的RoR-Tutorial,但实际上我在第10.4章遇到了问题。我做了所有的清单,最高达到10.42,但我的3次Rspec测试都失败了。

它说:

  

1)用户admin属性应该响应admin   失败/错误:@ user = User.create!(@ attr)   ActiveRecord :: RecordInvalid:验证失败:名称不能为空,   电子邮件不能为空,电子邮件无效,密码不能为空,   密码太短(最少6个字符)   ./spec/requests/users_spec.rb:52:in块(3级)

     

2)默认情况下,用户admin属性不应该是管理员   失败/错误:@ user = User.create!(@ attr)   ActiveRecord :: RecordInvalid:验证失败:名称不能为空,   电子邮件不能为空,电子邮件无效,密码不能为空,   密码太短(最少6个字符)   ./spec/requests/users_spec.rb:52:in块(3级)

     

3)用户admin属性应该可以转换为admin   失败/错误:@ user = User.create!(@ attr)   ActiveRecord :: RecordInvalid:验证失败:名称不能为空,   电子邮件不能为空,电子邮件无效,密码不能为空,   密码太短(最少6个字符)   ./spec/requests/users_spec.rb:52:in块(3级)

我已经仔细查看了我的users_controllers_spec.rb和我的user_spec.rb,但我找不到错误的解释。有没有人有想法?

require 'spec_helper'

describe UsersController do
  render_views

  describe "GET 'index'" do

    describe "for non-signed-in users" do
      it "should deny access" do
        get :index
        response.should redirect_to(signin_path)
        flash[:notice].should =~ /sign in/i
      end
    end

    describe "for signed-in users" do

      before(:each) do
        @user = test_sign_in(Factory(:user))
        second = Factory(:user, :name => "Bob", :email => "another@example.com")
        third  = Factory(:user, :name => "Ben", :email => "another@example.net")
        #@users = [@user, second, third]
        @users = [@user, second, third]
        30.times do
          @users << Factory(:user, :name => Factory.next(:name),
                                   :email => Factory.next(:email))
        end
      end


      it "should be successful" do
        get :index
        response.should be_success
      end

      it "should have the right title" do
        get :index
        response.should have_selector("title", :content => "All users")
      end

    it "should have an element for each user" do
        get :index
        @users[0..2].each do |user|
          response.should have_selector("li", :content => user.name)
        end
      end

      it "should paginate users" do
        get :index
        response.should have_selector("div.pagination")
        response.should have_selector("span.disabled", :content => "Previous")
        response.should have_selector("a", :href => "/users?escape=false&page=2",
                                           :content => "2")
        response.should have_selector("a", :href => "/users?escape=false&page=2",
                                           :content => "Next")
      end
    end
  end



   describe "GET 'show'" do

        before(:each) do
          @user = Factory(:user)
        end

        it "should be successful" do
          get :show, :id => @user
          response.should be_success
        end

        it "should find the right user" do
          get :show, :id => @user
          assigns(:user).should == @user
        end

     it "should have the right title" do
          get :show, :id => @user
          response.should have_selector("title", :content => @user.name)
        end

        it "should include the user's name" do
          get :show, :id => @user
          response.should have_selector("h1", :content => @user.name)
        end

        it "should have a profile image" do
          get :show, :id => @user
          response.should have_selector("h1>img", :class => "gravatar")
        end
      end

      describe "GET 'new'" do
        it "should be successful" do
          get 'new'
          response.should be_success
        end

        it "should have the right title" do
          get 'new'
          response.should have_selector("title", :content => "Sign up")
        end
      end
      describe "POST 'create'" do

        describe "failure" do

          before(:each) do
            @attr = { :name => "", :email => "", :password => "",
                      :password_confirmation => "" }
          end

          it "should not create a user" do
            lambda do
              post :create, :user => @attr
            end.should_not change(User, :count)
          end

          it "should have the right title" do
            post :create, :user => @attr
            response.should have_selector("title", :content => "Sign up")
          end

          it "should render the 'new' page" do
            post :create, :user => @attr
            response.should render_template('new')
          end
         end


        describe "success" do

          before(:each) do
            @attr = { :name => "New User", :email => "user@example.com",
                      :password => "foobar", :password_confirmation => "foobar" }
          end

          it "should create a user" do
            lambda do
              post :create, :user => @attr
            end.should change(User, :count).by(1)
          end

          it "should redirect to the user show page" do
            post :create, :user => @attr
            response.should redirect_to(user_path(assigns(:user)))
          end    

          it "should have a welcome message" do
            post :create, :user => @attr
            flash[:success].should =~ /welcome to the sample app/i
          end

          it "should sign the user in" do
            post :create, :user => @attr
            controller.should be_signed_in
          end


        end
      end
    describe "GET 'edit'" do

        before(:each) do
          @user = Factory(:user)
          test_sign_in(@user)
        end

        it "should be successful" do
          get :edit, :id => @user
          response.should be_success
        end

        it "should have the right title" do
          get :edit, :id => @user
          response.should have_selector("title", :content => "Edit user")
        end

        it "should have a link to change the Gravatar" do
          get :edit, :id => @user
          gravatar_url = "http://gravatar.com/emails"
          response.should have_selector("a", :href => gravatar_url,
                                             :content => "change")
        end
      end
     describe "PUT 'update'" do

        before(:each) do
          @user = Factory(:user)
          test_sign_in(@user)
        end

        describe "failure" do

          before(:each) do
            @attr = { :email => "", :name => "", :password => "",
                      :password_confirmation => "" }
          end

          it "should render the 'edit' page" do
            put :update, :id => @user, :user => @attr
            response.should render_template('edit')
          end

          it "should have the right title" do
            put :update, :id => @user, :user => @attr
            response.should have_selector("title", :content => "Edit user")
          end
        end

        describe "success" do

          before(:each) do
            @attr = { :name => "New Name", :email => "user@example.org",
                      :password => "barbaz", :password_confirmation => "barbaz" }
          end

          it "should change the user's attributes" do
            put :update, :id => @user, :user => @attr
            @user.reload
            @user.name.should  == @attr[:name]
            @user.email.should == @attr[:email]
          end

          it "should redirect to the user show page" do
            put :update, :id => @user, :user => @attr
            response.should redirect_to(user_path(@user))
          end

          it "should have a flash message" do
            put :update, :id => @user, :user => @attr
            flash[:success].should =~ /updated/
          end
        end
      end
    describe "authentication of edit/update pages" do

        before(:each) do
          @user = Factory(:user)
        end

        describe "for non-signed-in users" do

          it "should deny access to 'edit'" do
            get :edit, :id => @user
            response.should redirect_to(signin_path)
          end

          it "should deny access to 'update'" do
            put :update, :id => @user, :user => {}
            response.should redirect_to(signin_path)
          end
        end

      describe "for signed-in users" do

          before(:each) do
            wrong_user = Factory(:user, :email => "user@example.net")
            test_sign_in(wrong_user)
          end

          it "should require matching users for 'edit'" do
            get :edit, :id => @user
            response.should redirect_to(root_path)
          end

          it "should require matching users for 'update'" do
            put :update, :id => @user, :user => {}
            response.should redirect_to(root_path)
          end
        end
      end

    describe "DELETE 'destroy'" do

        before(:each) do
          @user = Factory(:user)
        end

        describe "as a non-signed-in user" do
          it "should deny access" do
            delete :destroy, :id => @user
            response.should redirect_to(signin_path)
          end
        end

        describe "as a non-admin user" do
          it "should protect the page" do
            test_sign_in(@user)
            delete :destroy, :id => @user
            response.should redirect_to(root_path)
          end
        end

        describe "as an admin user" do

          before(:each) do
            admin = Factory(:user, :email => "admin@example.com", :admin => true)
            test_sign_in(admin)
          end

          it "should destroy the user" do
            lambda do
              delete :destroy, :id => @user
            end.should change(User, :count).by(-1)
          end

          it "should redirect to the users page" do
            delete :destroy, :id => @user
            response.should redirect_to(users_path)
          end
        end
      end
    end

这是我的user_spec.rb

require 'spec_helper'

describe User do

  before(:each) do
    @attr = {
      :name => "Example User",
      :email => "user@example.com",
      :password => "foobar",
      :password_confirmation => "foobar"
    }
  end

  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[user@foo.com THE_USER@foo.bar.org first.last@foo.jp]
    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[user@foo,com user_at_foo.org example.user@foo.]
    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 "password validations" do

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

    it "should require a matching password confirmation" do
      User.new(@attr.merge(:password_confirmation => "invalid")).
        should_not be_valid
    end

    it "should reject short passwords" do
      short = "a" * 5
      hash = @attr.merge(:password => short, :password_confirmation => short)
      User.new(hash).should_not be_valid
    end

    it "should reject long passwords" do
      long = "a" * 41
      hash = @attr.merge(:password => long, :password_confirmation => long)
      User.new(hash).should_not be_valid
    end
  end

  describe "password encryption" do

    before(:each) do
      @user = User.create!(@attr)
    end

    it "should have an encrypted password attribute" do
      @user.should respond_to(:encrypted_password)
    end

    it "should set the encrypted password" do
      @user.encrypted_password.should_not be_blank
    end

    describe "has_password? method" do

      it "should be true if the passwords match" do
        @user.has_password?(@attr[:password]).should be_true
      end    

      it "should be false if the passwords don't match" do
        @user.has_password?("invalid").should be_false
      end 
    end
  end     
  describe "authenticate method" do

      it "should return nil on email/password mismatch" do
        wrong_password_user = User.authenticate(@attr[:email], "wrongpass")
        wrong_password_user.should be_nil
      end

      it "should return nil for an email address with no user" do
        nonexistent_user = User.authenticate("bar@foo.com", @attr[:password])
        nonexistent_user.should be_nil
      end

      it "should return the user on email/password match" do
        matching_user = User.authenticate(@attr[:email], @attr[:password])
        matching_user.should == @user
      end
  end

  describe "admin attribute" do

    before(:each) do
      @user = User.create!({
      :name => "Example User",
      :email => "user@example.com",
      :password => "foobar",
      :password_confirmation => "foobar"
    })#(@attr)  

//EDIT: I tried both, the fill-in by hand an the original code with (@attr) --> nothing changes, still the same mistake

    end

    it "should respond to admin" do
      @user.should respond_to(:admin)
    end

    it "should not be an admin by default" do
      @user.should_not be_admin
    end

    it "should be convertible to an admin" do
      @user.toggle!(:admin)
      @user.should be_admin
    end
  end
end

编辑:User.rb

 == Schema Information

 Table name: users

  id         :integer         not null, primary key
  name       :string(255)
  email      :string(255)
  created_at :datetime
  updated_at :datetime
//it's outcommented

class User < ActiveRecord::Base
 attr_accessor :password
  attr_accessible :name, :email, :password, :password_confirmation

 email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i


validates :name, :presence => true,
:length   => { :maximum => 50 }

 validates :email, :presence => true,
 :format   => { :with => email_regex },
 :uniqueness => { :case_sensitive => false }

 validates :password, :presence     => true,
                       :confirmation => true,
                       :length       => { :within => 6..40 }

  before_save :encrypt_password

   def has_password?(submitted_password)
    encrypted_password == encrypt(submitted_password)
  end

  def self.authenticate_with_salt(id, cookie_salt)
    user = find_by_id(id)
    (user && user.salt == cookie_salt) ? user : nil
  end

  def self.authenticate(email, submitted_password)
    user = find_by_email(email)
    return nil  if user.nil?
    return user if user.has_password?(submitted_password)
  end

   def self.authenticate(email, submitted_password)
    user = find_by_email(email)
    return nil  if user.nil?
    return user if user.has_password?(submitted_password)
  end

  private

    def encrypt_password
      self.salt = make_salt unless has_password?(password)
      self.encrypted_password = encrypt(password)
    end

    def encrypt(string)
      secure_hash("#{salt}--#{string}")
    end

    def make_salt
      secure_hash("#{Time.now.utc}--#{password}")
    end

    def secure_hash(string)
      Digest::SHA2.hexdigest(string)
    end



end

如果缺少一些重要的细节,请问,我准备更新这篇文章(只是不想超载它,因为代码已经足够大了)。

感谢您的关注!

2 个答案:

答案 0 :(得分:1)

我刚刚遇到同样的问题并通过从create方法调用中删除bang(!)来解决它:

@user = User.create(@attr)

HTH

答案 1 :(得分:0)

您的user_spec.rb与教程中的清单10.34中的不匹配。 更具体地说,before(:each)块。

你的user_spec.rb:

before(:each) do
    @user = User.create!({
    :name => "Example User",
    :email => "user@example.com",
    :password => "foobar",
    :password_confirmation => "foobar"
    })#(@attr)
end

清单10.34:

before(:each) do
    @user = User.create!(@attr)
end