Я закончил часть учебника 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. Почему это произойдет?
Дайте мне знать, если мне нужно будет добавить более подробную информацию.
Спасибо! Я понимаю, что ты имеешь в виду! Я изменил его на @user && @ user.password_reset_expired? И это сработало! – Olivia