问题
I am practicing Ruby on Rails by trying to create a custom website based off of Hartl's tutorial. Things have been going well so far but I am getting an error in the users edit test "Successful edit with friendly forwarding" in which the user is not redirected back to the edit page after logging in. This is the error message I get:
FAIL["test_successful_edit_with_friendly_forwarding", UsersEditTest, 3.1409137547016144]
test_successful_edit_with_friendly_forwarding#UsersEditTest (3.14s)
Expected response to be a redirect to <http://www.example.com/users/787258272/edit> but was a redirect to <http://www.example.com/users/787258272>.
Expected "http://www.example.com/users/787258272/edit" to be === "http://www.example.com/users/787258272".
test/integration/users_edit_test.rb:23:in `block in <class:UsersEditTest>'
I feel like the solution is something really simple that I missed but I can't seem to figure out what it is.
Here is my users_controller:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
log_in @user
flash[:success] = "Account created, welcome to Amplifire Energetics!"
redirect_to @user
else
render 'new'
end
end
def edit
end
def update
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)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
Here is my sessions_controller:
class SessionsController < ApplicationController
def new
end
def create
# Finds user in databse by email
@user = User.find_by(email: params[:session][:email].downcase)
# Authenticates user based on password
if @user && @user.authenticate(params[:session][:password])
log_in @user
params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
redirect_back_or @user
else
flash.now[:danger] = "Invalid email/password combination"
render 'new'
end
end
def destroy
log_out if logged_in?
redirect_to root_url
end
end
Here is my sessions_helper
module SessionsHelper
# Logs in user
def log_in(user)
session[:user_id] = user.id
end
# Remebers user in persistent session
def remember(user)
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
end
# Returns true if the given user is the current user.
def current_user?(user)
user == current_user
end
# Returns current logged in user
def current_user
if (user_id = session[:user_id])
@current_user ||= User.find_by(id: session[:user_id])
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
@current_user = user
end
end
end
# Returns true if user logged in
def logged_in?
!current_user.nil?
end
# Logs out user
def log_out
session.delete(:user_id)
@current_user = nil
end
# Forgets a persistent session
def forget(user)
user.forget
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
# Logs out current user
def log_out
forget(current_user)
session.delete(:user_id)
@current_user = nil
end
# Redirects to stored location (or to the default).
def redirect_back_or(default)
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
end
# Stores the URL trying to be accessed.
def store_location
session[:forwarding_url] = request.original_url if request.get?
end
end
Here is my routes file:
Rails.application.routes.draw do
get 'sessions/new'
get 'users/new'
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
Here is my users.yml file:
example:
name: Lil Wayne
email: wheezy@youngmoney.com
password_digest: <%= User.digest('password') %>
admin: true
archer:
name: Sterling Archer
email: dutchess@isis.gov
password_digest: <%= User.digest('password') %>
admin: false
Here is my user model file:
class User < ApplicationRecord
attr_accessor :remember_token
before_save :downcase_email
validates :name, presence: true, length: { maximum: 50 }
EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 245 },
format: { with: EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
class << self
# Returns hash digest of given string
def digest(s)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(s, cost: cost)
end
# Returns random token
def new_token
SecureRandom.urlsafe_base64
end
end
# Remembers user in database for persistent sessions
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
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
private
def downcase_email
self.email = email.downcase
end
end
And here is my users_edit_test:
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
@user = users(:example)
end
test "unsuccessful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user: { name: "",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar" } }
assert_template 'users/edit'
end
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_path(@user)
name = "Foo Bar"
email = "foo@bar.com"
patch user_path(@user), params: { user: { name: name,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal name, @user.name
assert_equal email, @user.email
end
end
回答1:
I found out what my problem was, I forgot to add the store_location method to the logged_in_user method in the users_controller.
来源:https://stackoverflow.com/questions/39647760/hartl-ruby-on-rails-tutorial-4-ch-10-users-edit-test-fails