Ошибка регистрации пользователя в учебнике М.Хартла по Rails
Я следил за учебником М. Хартла по Rails и столкнулся с проблемой. Когда я перешел из главы 10, все по коду работало, и мой набор тестов проходил. В главе 11 все, что я до сих пор делал, - это создание новой ветви. Ни один из моих файлов не был изменен. Тем не менее, так или иначе, мой набор тестов сейчас не работает. Еще более странным является то, что он не терпит неудачу в 100% случаев. Иногда это проходит, но в большинстве случаев происходит сбой (если я запускаю его снова и снова без изменения какого-либо кода). Соответствующий код и сообщение об ошибке ниже. Любая помощь будет принята с благодарностью. Спасибо
Ошибка:
FAIL["test_valid_signup_information_with_account_activation", UsersSignupTest, 3.902866843]
test_valid_signup_information_with_account_activation#UsersSignupTest (3.90s)
Expected: 1
Actual: 2
test/integration/users_signup_test.rb:29:in `block in <class:UsersSignupTest>'
user_signup_test.rb
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: {name: "Stevan",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar"}
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.alert-danger'
end
test "valid signup information with account activation" do
get signup_path
#name = "Example User"
#email = "user@example.com"
#password = "password"
assert_difference 'User.count', 1 do
post users_path, user:{name: "Example User",
email: "user@example.com",
password: "password",
password_confirmation: "password"}
end
assert_equal 1, ActionMailer::Base.deliveries.size
user = assigns(:user)
assert_not user.activated?
# Try to log in before activation.
log_in_as(user)
assert_not is_logged_in?
# Invalid activation token
get edit_account_activation_path("invalid token")
assert_not is_logged_in?
# Valid token, wrong email
get edit_account_activation_path(user.activation_token, email: 'wrong')
assert_not is_logged_in?
# Valid activation token
get edit_account_activation_path(user.activation_token, email: user.email)
assert user.reload.activated?
follow_redirect!
assert_template 'users/show'
assert is_logged_in?
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.paginate(page: params[:page])
end
def new
@user = User.new
end
def show
@user = User.find(params[:id])
end
def create
@user = User.new(user_params)
if @user.save
#UserMailer.account_activation(@user).deliver #deliver_now
@user.send_activation_email
flash[:info] = "Please check your email to activate your account"
redirect_to root_url
else
render 'new'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
def edit
#@user = User.find(params[:id]) no longer needed as we have implemented correct_user
end
def update
#@user = User.find(params[:id]) no longer needed as we have implemented correct_user
if @user.update_attributes(user_params)
flash[:success] = 'Profile updated'
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation) #haven't permit admin -> not editable in the browser
end
#before filters
#confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
#confirms the currect user is the user currently logged in
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user) #@user==current_user refactored
end
#confirms as admin user
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
user.rb
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
validates(:name, presence:true , length: {maximum: 50})
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]{2,4}+\z/i
validates(:email, presence:true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false})
has_secure_password
validates :password, length: {minimum: 6}, allow_blank: true
#returns the hash digest of the given string
def User.digest(string) #more idimatically correct to define as self.digest
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 #more idiomatically correct to define as self.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
#activates an account
def activate
update_attribute(:activated, true)
update_attribute(:activated_at, Time.zone.now)
end
#send activation email
def send_activation_email
UserMailer.account_activation(self).deliver
end
#sets the password reset attrobutes
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
#sends password reset email
def send_password_reset_email
UserMailer.password_reset(self).deliver
end
#Returns true if password has expired
def password_reset_expired?
reset_sent_at < 2.hours.ago
end
private
#converts email all to lower case
def downcase_email
self.email = email.downcase
end
#creates and assigns activation token and digest
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
Gemfile
source 'https://rubygems.org'
ruby '2.1.1'
gem 'rails', '4.2.0.beta1'
gem 'bcrypt', '3.1.7'
gem 'faker', '1.4.2'
gem 'will_paginate', '3.0.7'
gem 'bootstrap-will_paginate','0.0.10'
gem 'byebug', '3.5.1'
gem 'bootstrap-sass', '3.2.0.0'
gem 'sass-rails', '5.0.0.beta1'
gem 'uglifier', '2.5.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.1.1'
gem 'turbolinks', '2.3.0'
gem 'jbuilder', '2.1.3'
gem 'sdoc', '0.4.0', group: :doc
group :test do
gem 'minitest-reporters', '1.0.5'
gem 'mini_backtrace', '0.1.3'
gem 'guard-minitest', '2.3.1'
end
group :development do
gem 'sqlite3', '1.3.9'
gem 'spring', '1.1.3'
end
group :production do
gem 'pg', '0.17.1'
gem 'rails_12factor', '0.0.2'
gem 'unicorn', '4.8.3'
end
2 ответа
В вашем коде отсутствует setup
метод, определенный в листинге 10.29.
Попробуйте добавить следующее перед подключением ко всем спецификациям, касающимся ActionMailer
before { ActionMailer::Base.deliveries = [] }
Похоже, что другие спецификации также отправлять электронные письма. Результаты варьируются из-за произвольного порядка спецификаций.