2015-07-07 7 views
1

Я закончил часть учебника Michael Hartl, и я пытаюсь добавить функциональность сброса пароля (из главы 10) в свое приложение. Я не хочу функциональности активации, поэтому я не добавил этого. НО я обязательно добавил части, которые были релевантны почтовой программе «Сброс пароля» (например, аутентифицированный метод).NoMethodError: undefined method `password_reset_expired? ' for nil: NilClass

Когда я бегу rake, вот что я получаю:

ERROR["test_password_resets", PasswordResetsTest, 2015-07-06 17:12:16 -0700] 
test_password_resets#PasswordResetsTest (1436227936.11s) 
NoMethodError:   NoMethodError: undefined method `password_reset_expired?' for nil:NilClass 
      app/controllers/password_resets_controller.rb:60:in `check_expiration' 
      test/integration/password_resets_test.rb:26:in `block in <class:PasswordResetsTest>' 
     app/controllers/password_resets_controller.rb:60:in `check_expiration' 
     test/integration/password_resets_test.rb:26:in `block in <class:PasswordResetsTest>' 

    33/33: [=================================] 100% Time: 00:00:01, Time: 00:00:01 

Finished in 1.10830s 
33 tests, 83 assertions, 0 failures, 1 errors, 0 skips 

Вот мой Пароль Сбрасывает контроллер:

class PasswordResetsController < ApplicationController 
    before_action :get_user, only: [:edit, :update] 
    before_action :valid_user, only: [:edit, :update] 
    before_action :check_expiration, only: [:edit, :update] 

    def new 
    end 

    def create 
    @user = User.find_by(email: params[:password_reset][:email].downcase) 
    if @user 
     @user.create_reset_digest 
     @user.send_password_reset_email 
     flash[:info] = "An email was sent to " + @user.email + " with password reset instructions." 
     redirect_to login_url 
    else 
     flash.now[:danger] = "Hmm. We don't recognize that email. Make sure you signed up with this email." 
     render 'new' 
    end 
    end 

    def edit 
    end 

    def update 
    if params[:user][:password].empty? 
     flash.now[:danger] = "Uh oh. Your password can't be empty." 
     render 'edit' 
    elsif @user.update_attributes(user_params) 
     log_in @user 
     flash[:success] = "Success! Your password has been reset!" 
     redirect_to @user 
    else 
     render 'edit' 
    end 
    end 

    private 

    def user_params 
    params.require(:user).permit(:password, :password_confirmation) 
    end 

    #BEFORE FILTERS 

    def get_user 
    @user = User.find_by(email: params[:email]) 
    end 

    # Confirms a valid user. 
    def valid_user 
    if (@user && @user.authenticated?(:reset, params[:id])) 
     redirect_to root_url 
     puts("Either I don't exist or I'm not authenticated.") 
    end 
    end 

    # Checks expiration of reset token. 
    def check_expiration 
    if @user.password_reset_expired? 
     flash[:danger] = "Uh oh! Your password reset has expired. Please request a new password reset." 
     redirect_to new_password_reset_url 
    end 
    end 

end 

А вот моя модель пользователя:

class User < ActiveRecord::Base 
    attr_accessor :remember_token, :reset_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 #Set valid email regex to be used 
    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 }, allow_nil: true 

    # 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?(attribute, token) 
     digest = send("#{attribute}_digest") 
     return false if digest.nil? 
     BCrypt::Password.new(digest).is_password?(token) 
    end 

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

    #PASSWORD RESET 
     def create_reset_digest 
     self.reset_token = User.new_token 
     update_attribute(:reset_digest, User.digest(reset_token)) 
     update_attribute(:reset_sent_at, Time.zone.now) 
     end 

     def send_password_reset_email 
     UserMailer.password_reset(self).deliver_now 
     end 

     # Returns true if a password reset has expired. 
     def password_reset_expired? 
     reset_sent_at < 2.hours.ago 
     end 

end 

Я проверил мое правописание, и снова и снова, но это не имеет значения, даже если я изменю имя fu nction. Что происходит?

Кстати, когда я физически пытаюсь использовать сброс пароля в localhost: 3000, в нем говорится, что было отправлено письмо с подтверждением (но я не получаю его, поскольку я думаю, что это часть localhost). Затем, когда я посещаю предварительный просмотр почтового ящика и использую пароль сброса, он отлично работает. Но в производстве (на Heroku), если я попытаюсь ввести свой адрес электронной почты, чтобы получить отправленное письмо с подтверждением, я просто получаю страницу с ошибкой - 500. Почему это произойдет?

Дайте мне знать, если мне нужно будет добавить более подробную информацию.

ответ

2

Если ваш пользователь не найден (например, нет пользователя с указанным адресом электронной почты) ... что происходит, когда вы пытаетесь проверить его истечение?

Подсказка: посмотрите на то, что вы делаете в valid_user для примера того, что вы должны сделать в check_expiration

+1

Спасибо! Я понимаю, что ты имеешь в виду! Я изменил его на @user && @ user.password_reset_expired? И это сработало! – Olivia

Смежные вопросы