2012-01-23 44 views
0

我是RoR學習者,我邁向Michael Hartl的RoR教程,但實際上我在第10.4章中遇到了問題。我做了所有的清單高達10.42,但我的Rspec測試3失敗。RoR教程(第10.4章) - 管理員屬性測試失敗

它說:

1) Users admin attribute should respond to admin Failure/Error: @user = User.create!(@attr) ActiveRecord::RecordInvalid: Validation failed: Name can't be blank, Email can't be blank, Email is invalid, Password can't be blank, Password is too short (minimum is 6 characters) ./spec/requests/users_spec.rb:52:in `block (3 levels) in

2) Users admin attribute should not be an admin by default Failure/Error: @user = User.create!(@attr) ActiveRecord::RecordInvalid: Validation failed: Name can't be blank, Email can't be blank, Email is invalid, Password can't be blank, Password is too short (minimum is 6 characters) ./spec/requests/users_spec.rb:52:in `block (3 levels) in

3) Users admin attribute should be convertible to an admin Failure/Error: @user = User.create!(@attr) ActiveRecord::RecordInvalid: Validation failed: Name can't be blank, Email can't be blank, Email is invalid, Password can't be blank, Password is too short (minimum is 6 characters) ./spec/requests/users_spec.rb:52:in `block (3 levels) in

我已經把我的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 => "[email protected]") 
     third = Factory(:user, :name => "Ben", :email => "[email protected]") 
     #@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 => "[email protected]", 
         :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 => "[email protected]", 
         :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 => "[email protected]") 
      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 => "[email protected]", :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 => "[email protected]", 
     :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[[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 "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("[email protected]", @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 => "[email protected]", 
     :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+\-.][email protected][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 

如果一些重要的細節丟失,請問,我準備更新這個帖子(只是不想重載它,因爲代碼已經足夠大)。

感謝您的關注!

回答

1

我最近剛剛碰到同樣的問題,並通過從創建方法調用中的感嘆號(!)解決它:

@user = User.create(@attr) 

HTH

+0

我沒有線索爲什麼,但它的作品! 謝謝! –

0

您的user_spec.rb與本教程中的代碼清單10.34中的代碼不匹配。 更具體地說,before(:each)塊。

您user_spec.rb:

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

清單10.34:

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

嗯,我以前(#(@ attr)),但它沒有奏效。所以我只是試圖自己填寫它,看看錯誤是否會改變。但它們完全相同,並且(@attr)。 (只想顯示,我已經嘗試過)。 –

+0

我真的懷疑這個(:它的奇怪,因爲它似乎在前面的例子中工作,我不能認爲'@ attr'在任何地方發生了變化,也許你可以嘗試去除'{'和'}'屬性,不知道這是否有所作爲 – jlundqvist

+0

這就是事情,我也不明白:/爲什麼,(@attr)突然不工作?我只是試圖離開{和}出去,但你是對的,沒有什麼區別 –

相關問題