2015-11-21 52 views
2

我從rubytutorial學習,並有這個錯誤。 我檢查了this答案和this但仍然無法正常工作。 我在這裏附加了session_helper.rb和user.rb。 有人可以告訴我我錯過的地方嗎?第8章rubytutorial - NoMethodError:undefined方法`忘記'爲零:NilClass

1) Error: 
UsersLoginTest#test_login_with_valid_information_followed_by_logout: 
NoMethodError: undefined method `forget' for nil:NilClass 
    app/helpers/sessions_helper.rb:25:in `forget' 
    app/helpers/sessions_helper.rb:32:in `log_out' 
    app/controllers/sessions_controller.rb:19:in `destroy' 
    test/integration/users_login_test.rb:33:in `block in <class:UsersLoginTest>' 

22 runs, 50 assertions, 0 failures, 1 errors, 0 skips 

session_helper.rb

module SessionsHelper 
    # Logs in the given user. 
    def log_in(user) 
     session[:user_id] = user.id 
    end 

    def current_user 
    if (user_id = session[:user_id]) 
     @current_user ||= User.find_by(id: user_id) 
    elsif (user_id = cookies.signed[:user_id]) 
     user = User.find_by(id: user_id) 
    if user && user.authenticated?(cookies[:remember_token]) 
     log_in user 
     @current_user = user 
     end 
    end 
    end 

    def logged_in? 
     !current_user.nil? 
    end 

    # Forgets a persistent session. 
    def forget(user) 
     user.forget 
     cookies.delete(:user_id) 
     cookies.delete(:remember_token) 
    end 

    # Logs out the current user. 
    def log_out 
     forget(current_user) 
     session.delete(:user_id) 
     @current_user = nil 
    end 

    # Remembers a user in a persistent session. 
    def remember(user) 
     user.remember 
     cookies.permanent.signed[:user_id] = user.id 
     cookies.permanent[:remember_token] = user.remember_token 
    end 
    end 

user.rb

class User < ActiveRecord::Base 
    attr_accessor :remember_token 
    before_save { self.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, length: { maximum: 255 }, 
        format: { with: VALID_EMAIL_REGEX }, 
        uniqueness: { case_sensitive: false } 
    has_secure_password 
    validates :password, presence: true, length: { minimum: 6 } 

    # Returns the hash digest of the given string. 
    def User.digest(string) 
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 
                BCrypt::Engine.cost 
    BCrypt::Password.create(string, cost: cost) 
    end 

    # Returns a random token. 
    def User.new_token 
    SecureRandom.urlsafe_base64 
    end 

    # Remembers a user in the database for use in persistent sessions. 
    def remember 
    self.remember_token = User.new_token 
    update_attribute(:remember_digest, User.digest(remember_token)) 
    end 

    # Returns true if the given token matches the digest. 
    def authenticated?(remember_token) 
    return false if remember_digest.nil? 
    BCrypt::Password.new(remember_digest).is_password?(remember_token) 
    end 

    # Forgets a user. 
    def forget 
    update_attribute(:remember_digest, nil) 
    end 
end 

回答

2

你的錯誤信息表明你有一個:

undefined method forget' for nil:NilClass

這意味着你試圖調用一種方法(forget)在沒有該方法的對象上(nil)。看你的代碼,其中的誤差是來自部分...

def forget(user) 
     user.forget 

...你可以看到你正在呼籲忘記在變量user。這是正在從log_out方法叫:

def log_out 
    forget(current_user) 

所以,你是路過current_userforget方法,然後調用它forget。只有它不是User類的一個實例(就像你期望的那樣),它有一個forget方法,而是nilnil沒有忘記方法。

這可能是零,因爲您沒有通過身份驗證,也沒有current_user。要解決這個問題的方法之一是忘記之前檢查當前用戶是否確實存在,像這樣:

def log_out 
    current_user && forget(current_user) 

更復雜的方式來處理這個問題將與Null Object Pattern,其中current_user將返回的實例擁有最少授權的用戶,而不是零。

+0

感謝您的回答。但我仍然不知道該怎麼做。 :) 你的意思是說數據庫是空的? – Codelearner777

+0

@ Codelearner777不,我的意思是沒有登錄(或認證)的用戶。 「無」意味着「無」。像上面的例子那樣改變你的代碼,看看會發生什麼。 –

+0

我試了一下,它的工作原理!謝謝。 雖然我仍然不明白,並且正在閱讀第8章。 我真的很感謝你的幫助。 – Codelearner777

1

看看你的日誌,你試圖調用.forgetnil對象:

NoMethodError: undefined method `forget' for nil:NilClass 

這意味着你通過nilSessionsHelper#forget,所以你current_usernil

您是否嘗試註銷當前未登錄的用戶?如果沒有,則方法current_user應該出現問題,因爲用戶已經登錄時它會返回nil

+1

jinx,你得到+1 –

+0

大聲笑,我注意到我們同時發佈答案,但我忘了jinx你:) :) –

+0

感謝您的回答。但我仍然不知道該怎麼做。 :) – Codelearner777

1

Soooo,我意識到這就像2年後...但我在這裏有同樣的問題作爲OP ...

我的解決辦法(如教程解釋)從更改SessionsControllerdestroy方法:

def destroy 
    log_out 
    redirect_to root_url 
end 

到:

def destroy 
    log_out if logged_in? 
    redirect_to root_url 
end 

萬一別人是遲到了軌遊戲,因爲我...希望這可以幫助

相關問題