对于#<user:0x0000010b454f50>,未定义的方法`remember_token ='

时间:2015-06-02 03:20:15

标签: ruby-on-rails-4 railstutorial.org

我正在使用Rails Tutorial并且遇到了第8章 - 关于登录会话的问题。当我提交应该创建新会话的电子邮件/密件组合时,会出现错误。

这是错误:

NoMethodError in SessionsController#create
undefined method `remember_token=' for #<User:0x0000010b454f50>

Extracted source (around line #435):
      else
        match = match_attribute_method?(method.to_s)
        match ? attribute_missing(match, *args, &block) : super
      end
    end

从那里我在会话控制器中查看create。我试着看看我在哪里调用remember_token方法。

会话控制器:

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
      #if 1 then remember, else forget
      params[:session][:remember_me] == '1' ? remember(user) : forget(user)

      remember user

      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination' 
      render 'new'
    end

  end

  def destroy
    #call log_out helper method
    log_out if logged_in?

    redirect_to root_url
  end


end

我致电remember这看起来很重要。这是会话助手:

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

  def remember(user)
    #generate a new token and provide the encrypted hash
    user.remember

    cookies.permanent.signed[:user_id]=user.id
    cookies.permanent[:remember_token]=user.remember_token
  end

  def current_user
    #if session user id exists, then set to user_id and then...
    if (user_id = session[:user_id])
      #set @current_user to the correct user account
      @current_user||= User.find_by(id: user_id)

    #else, if signed cookie user id exists, set to user_id and then...
    elsif (user_id = cookies.signed[:user_id])
      #set user to the correct user account and...
      user = User.find_by(id: user_id)
      #if user is authenticated, then log them in and set @current_user to user
      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

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

end

看起来像是密钥 - cookies.permanent[:remember_token]=user.remember_token

但我不知道如何定义remember_token方法。当我浏览教程时,我没有看到任何描述remember_token的方法。我得到的最接近的是用户模型(方法称为remember):

class User < ActiveRecord::Base
before_save { self.email = email.downcase }

belongs_to :courses
belongs_to :lessons

validates :first_name,  presence: true, length: { maximum: 50 }
validates :last_name,  presence: true, length: { maximum: 50 }

validates :email, presence: true, length: { maximum: 255 }, 
     uniqueness: { case_sensitive: false }

has_secure_password
validates :password, 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::Password.create(string, cost: cost)

    BCrypt::Password.create(string, cost: cost)
  end

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

  #creates a new token (random string) then encypts it by returning a hash
  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

我是否了解会话控制器,会话助手和用户模型之间的相互作用?相互作用是不是设置正确 - 这是抛出错误?我不明白为什么它不起作用......

背景: 本教程有意避免将remember_token作为安全功能放在数据库中。所以这不是问题。

1 个答案:

答案 0 :(得分:-1)

问题在于会话控制器 - 我没有理解三元运算符并重复了一些功能。这是原始的创建方法:

  def create

    user = User.find_by(email: params[:session][:email].downcase)

    if user &&  user.authenticate(params[:session][:password])

      log_in user
      #if 1 then remember, else forget
      params[:session][:remember_me] == '1' ? remember(user) : forget(user)

      remember user

      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination' 
      render 'new'
    end

  end

这个位remember user是多余的。

三元params[:session][:remember_me] == '1' ? remember(user) : forget(user)表示如果params[:session][:remember_me]为1,则remember(user)为其他forget(user)

然后调用remember user(与remember(user)相同)我执行了两次相同的操作,导致错误。