2015-03-16 1 views
2

Работа через Rails Tutorial по М. Hartl Ch 8 Вход, ВыйтиNoMethodError в SessionsController # уничтожить неопределенный метод `забыть» для ноль: NilClass

При попытке выйти из моего приложения, я получаю сообщение об ошибке данный в названии моего вопроса.

Я новичок в этом, но я думаю, что это означает, что метод forget экземпляра определяется в models/user.rb и называется в SessionsHelper вызывается на user, который по какой-то причине это ноль. Вот фрагмент кода, я говорю о том, в SessionsHelper:

#Found in SessionHelper. Forgets persistent session 
def forget(user) 
    user.forget 
    cookies.delete(:user_id) 
    cookies.delete(:remember_tolken) 
end 

А вот определение метода forget экземпляра:

#Found in class models/user.rb 
def forget 
    update_attribute(:remember_digest, nil) 
end 

Я не знаю, почему пользователь будет ноль при вызове в SessionsHelper. Вот полные файлы, включая SessionsController, SessionsHelper и User.

Надеюсь, я был понятен и использовал правильную терминологию. Дайте мне знать, если мне нужно уточнить.

class SessionsController < ApplicationController 
    def new 
    end 

    def create 
    user = User.find_by(email: params[:session][:email].downcase) 
    if user && user.authenticate(params[:session][:password]) 
     log_in user # Log the user in and redirect to the user's showpage 
     params[:session][:remember_me] == '1' ? remember(user) : forget(user) 
     redirect_to user # same as user_url(user) 
    else 
     # Show error message 
     flash.now[:danger] = 'Wrong email or password' 
     render 'new' 
    end 
    end 

    def destroy 
    log_out # if logged_in? # not logging out 
    redirect_to root_url 
    end 
end 

XXXXXXXXXX

module SessionsHelper 

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

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

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


# Returns the current logged-in user (if any) 
def current_user 
    if (user_id = session[:user_id]) # CAREFUL! (not ==). Read if session of user_id exists 
     @current_user ||= User.find_by(id: user_id) 
    else (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 

# Returns true if the user is logged-in, else false 
def logged_in? 
    !current_user.nil? 
end 

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

XXXXXXXXXX

class User < ActiveRecord::Base 
attr_accessor :remember_token 

    before_save {email.downcase!} 
    validates :name, presence: true, length: {maximum: 50} 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-]+(\.[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, length: {minimum: 6} 

    # Returns the hash digest of the given string. Used to make hashed password of user in fixture model for login integration testing               
    def User.digest(string) 
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 
                BCrypt::Engine.cost 
    BCrypt::Password.create(string, cost: cost) 
    end 

    # Returns random token for remembering users via cookies 
    def User.new_token 
    SecureRandom.urlsafe_base64 
    end 

    # Remembers a user in the database for use in persisten 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 

Спасибо

+1

Параметр 'метод current_user' возвращается ноль, когда он не должен. Я подозреваю эту строку: 'else (user_id = cookie.signed [: user_id])', я никогда не знал 'else', чтобы принять аргумент, поэтому он выглядит подозрительно для меня. Возможно, 'elsif'. –

ответ

1

Ваш метод log_out удаляет сеанс перед тем забыть пользователя. Это приводит к ошибке, потому что forget принимает current_user в качестве параметра и current_user использует сессию, чтобы определить, кто текущий пользователь:

if (user_id = session[:user_id]) # This will attempt to assign user_id based on the value of session[:user_id], but will fail since the session was deleted 

Вы должны удалить сеанс после позабыв пользователя. Измените метод log out от этого:

def log_out 
    session.delete(:user_id) 
    forget(current_user) 
    @current_user = nil 
end 

к этому:

def log_out 
    forget(current_user) 
    session.delete(:user_id) 
    @current_user = nil 
end 
+0

Это действительно решило проблему. Теперь очень очевидно, что вы указали это, спасибо! – user1486510

1

Метод current_user возвращается ноль, и далее бросать ошибку вниз по линии.

Опечатка в вашем методе current_user. Измените else на elsif, и это, скорее всего, устранит проблему.

Если это не исправить, убедитесь, что метод точно такой же, как в Listing 8.57 of the rails tutorial; то же приведена ниже:

# Returns the user corresponding to the remember token cookie. 
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 
+0

Я помню книгу, в которой описывается использование elseif в этой ситуации. Я получаю эту ошибку в браузере, когда я запускаю его, однако NoMethodError в SessionsController # уничтожить неопределенный метод 'ElseIf» для # @ решение BigRon по фиксированной исходной задачи, но я хотел бы понять, почему это не работает. – user1486510