我一直在研究M.Hartl的Ruby on Rails教程已经有一段时间了,我已经能够解决当我犯错误导致我的集成测试失败等问题时,但是我我遇到了一个我无法弄清楚的问题。我的get edit_password_reset_path()
具有正确的参数是重定向到主网址,而不是password_resets/edit
。
失败的测试:
FAIL["test_password_resets", PasswordResetsTest, 2015-11-02 15:50:02 +0000]
test_password_resets#PasswordResetsTest (1446479402.08s)
expecting <"password_resets/edit"> but rendering with <[]>
test/integration/password_resets_test.rb:37:in `block in <class:PasswordResetsTest>'
这是我的password_resets_test.rb:
require 'test_helper'
class PasswordResetsTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
@user = users(:michael)
end
test "password resets" do
get new_password_reset_path
assert_template 'password_resets/new'
# Invalid email
post password_resets_path, password_reset: { email: "" }
assert_not flash.empty?
assert_template 'password_resets/new'
# Valid email
post password_resets_path, password_reset: { email: @user.email }
assert_not_equal @user.reset_digest, @user.reload.reset_digest
assert_equal 1, ActionMailer::Base.deliveries.size
assert_not flash.empty?
assert_redirected_to root_url
# Password reset form
user = assigns(:user)
# Wrong email
get edit_password_reset_path(user.reset_token, email: "")
assert_redirected_to root_url
# Inactive user
user.toggle!(:activated)
get edit_password_reset_path(user.reset_token, email: user.email)
assert_redirected_to root_url
user.toggle!(:activated)
# Right email, wrong token
get edit_password_reset_path('wrong token', email: user.email)
assert_redirected_to root_url
# Right email, right token
get edit_password_reset_path(user.reset_token, email: user.email)
assert_template 'password_resets/edit' # This is the assertion that fails
assert_select "input[name=email][type=hidden][value=?]", user.email
# Invalid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobazzz",
password_confirmation: "barquuxz" }
assert_select 'div#error_explanation'
# Empty password
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "",
password_confirmation: "" }
assert_not flash.empty?
# Valid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobazzz",
password_confirmation: "foobazzz" }
assert is_logged_in?
assert_not flash.empty?
assert_redirected_to user
end
end
这是我的password_resets_controller.rb
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] = "Email sent with password reset instructions"
redirect_to root_url
else
flash.now[:danger] = "Email address not found"
render 'new'
end
end
def edit
end
def update
if params[:user][:password].empty?
@user.errors.add(:password, "can't be empty")
render 'edit'
elsif @user.update_attributes(user_params)
log_in @user
flash[:success] = "Password has been reset"
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
def get_user
@user = User.find_by(email: params[:email])
end
def valid_user
unless (@user && @user.activated? &&
@user.authenticated?(:reset, params[:id]))
redirect_to root_url
end
end
def check_expiration
if @user.password_reset_expired?
flash[:danger] = "Password reset has expired."
redirect_to new_password_reset_url
end
end
end
authenticated?
中的user.rb
方法:
# 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
我不确定还有什么需要弄清楚我的问题。我已经搜索了StackOverflow,第二次使用代码,我甚至比较了M.Hartl的github repo的源代码。
Link to the appropriate branch on my repo.
我正在努力完全遵循this part of the tutorial.
答案 0 :(得分:2)
问题出在user.rb
模型中。
在我的模型中,我有以下代码:
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_digest))
update_attribute(:reset_sent_at, Time.zone.now)
end
请注意第一个update_attribute()
来电的第二个参数reset_digest
。那应该是reset_token
。正确的方法如下所示:
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