Rails Tutorial Help on Chapter 9 - ruby-on-rails

I have run into 4 errors on section 9.2.2.
Errors
ERROR["test_unsuccessful_edit", UsersEditTest, 2015-11-05 04:35:59 -0600]
test_unsuccessful_edit#UsersEditTest (1446719759.23s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf48ad378>
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:10:in block in <class:UsersEditTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:10:in `block in '
ERROR["test_successful_edit", UsersEditTest, 2015-11-05 04:35:59 -0600]
test_successful_edit#UsersEditTest (1446719759.28s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdefcea198>
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:21:in block in <class:UsersEditTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:21:in `block in '
ERROR["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-11-05 04:35:59 -0600]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1446719759.42s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf529f778>
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:29:in block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:29:in `block in '
ERROR["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-11-05 04:35:59 -0600]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1446719759.44s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf531e118>
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:36:in block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:36:in `block in '
32/32: [======================] 100% Time: 00:00:01, Time: 00:00:01
Finished in 1.70355s
32 tests, 64 assertions, 0 failures, 4 errors, 0 skips
Users_controller.rb
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] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
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 correct_user?(#user)
end
end
User_controller_test
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when logged in" do
get :edit, id: #user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert flash.empty?
assert_redirected_to root_url
end
end
users.yml
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
users_edit_test
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "unsuccessful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: "",
email: "foo#invalid",
password: "foo",
password_confirmation: "bar" }
assert_template 'users/edit'
end
test "successful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
name = "Foo Bar"
email = "foo#bar.com"
patch user_path(#user), 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
I think that is all that would be needed to help. I have been struggling for some time now. This is my first post, sorry if it isn't easy to read.

correct_user? isn't defined anywhere.
redirect_to(root_url) unless correct_user?(#user)
Rails's syntactic sugar is going to look for a model flag correct_user or a boolean-returning function #correct_user? getter. I'm assuming that you're trying to validate that an update request from a user actually belongs to the correct user. To do this you must have current_user stored in a session, and then check the request param[:id] == current_user.id

Related

Ruby on rails tutorial - integration test - valid/invalid user info sign failing - user_param issue?

I'm plugging away after an extended leave (a year) on the Ruby on Rails Tutorial by Michael Hartl. I'm getting a user_param error in an integration test. I've gone to 4 sources trying to figure out where I'm going wrong on the strong parameters including the documentations.
Since starting up again last week, I have four hours generally getting to know the tutorial project and another twelve hours reading over chapters 7 to 12, then an hour chasing this problem. I keep feeling like I must be scanning too quickly over this stuff & keenly realizing I am not good at tracing errors.
Can anyone shed some light on what I'm missing? I'd also like any tips on trouble shooting this type of thing too! Thanks for your time!
Here's the error message I'm getting from console:
ERROR["test_password_resets", PasswordResetsTest, 2016-10-20 15:24:37 +0000]
test_password_resets#PasswordResetsTest (1476977077.03s)
NoMethodError: NoMethodError: undefined method `[]' for nil:NilClass
app/controllers/password_resets_controller.rb:10:in `create'
test/integration/password_resets_test.rb:14:in `block in <class:PasswordResetsTest>'
app/controllers/password_resets_controller.rb:10:in `create'
test/integration/password_resets_test.rb:14:in `block in <class:PasswordResetsTest>'
ERROR["test_invalid_signup_information", UsersSignupTest, 2016-10-20 15:24:37 +0000]
test_invalid_signup_information#UsersSignupTest (1476977077.04s)
ActionController::ParameterMissing: ActionController::ParameterMissing: param is missing or the value is empty: user
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:12:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:11:in `block in <class:UsersSignupTest>'
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:12:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:11:in `block in <class:UsersSignupTest>'
ERROR["test_valid_signup_information_with_account_activation", UsersSignupTest, 2016-10-20 15:24:37 +0000]
test_valid_signup_information_with_account_activation#UsersSignupTest (1476977077.05s)
ActionController::ParameterMissing: ActionController::ParameterMissing: param is missing or the value is empty: user
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:25:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:24:in `block in <class:UsersSignupTest>'
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:25:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:24:in `block in <class:UsersSignupTest>'
FAIL["test_should_get_edit", PasswordResetsControllerTest, 2016-10-20 15:24:37 +0000]
test_should_get_edit#PasswordResetsControllerTest (1476977077.05s)
Expected response to be a <success>, but was <302>
test/controllers/password_resets_controller_test.rb:11:in `block in <class:PasswordResetsControllerTest>'
Here's the controller in question (users_controller):
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 destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
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?
store_location
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
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Here's the user_signup_test:
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
end
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
end
test "valid signup information with account activation" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: { 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", email: user.email)
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
Here is the last controller - missed that one somehow ...
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'
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: "foobaz",
password_confirmation: "barquux" }
assert_select 'div#error_explanation'
# Empty password
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "",
password_confirmation: "" }
assert_select 'div#error_explanation'
# Valid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobaz",
password_confirmation: "foobaz" }
assert is_logged_in?
assert_not flash.empty?
assert_redirected_to user
end
end
PasswordResetController:
class PasswordResetsController < ApplicationController
before_action :get_user, only: [:edit, :update]
before_action :valid_user, only: [:edit, :update]
before_action :check_expiration, only: [:edit, :update] # Case (1)
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? # Case (3)
#user.errors.add(:password, "can't be empty")
render 'edit'
elsif #user.update_attributes(user_params) # Case (4)
log_in #user
flash[:success] = "Password has been reset."
redirect_to #user
else
render 'edit' # Case (2)
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
unless (#user && #user.activated? &&
#user.authenticated?(:reset, params[:id]))
redirect_to root_url
end
end
# Checks expiration of reset token.
def check_expiration
if #user.password_reset_expired?
flash[:danger] = "Password reset has expired."
redirect_to new_password_reset_url
end
end
end
I think you should remove params key before user parameters, e.g.:
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
end
Also you can debug received parameters in controller with pry:
add gem pry to your Gemfile (if there is no one);
run $ bundle install;
add binding.pry in controller before method user_params is called;
check that params contains expected parameters.

Hartl Rails Tutorial Ch9, "test_should_redirect_destroy_when_not_logged_in" error?

Working through Hartl's tutorial, in Chapter 9, Listing 9.56 produces the following error, showing 'admin?' as an undefined method.
I've checked (and rechecked) the 2 sections of code that have been revised since the last green test. Stumped.
ERROR["test_should_redirect_destroy_when_not_logged_in", UsersControllerTest, 2016-02-26 21:29:01 -0500]
test_should_redirect_destroy_when_not_logged_in#UsersControllerTest (1456540141.41s)
NoMethodError: NoMethodError: undefined method `admin?' for nil:NilClass
app/controllers/users_controller.rb:73:in `admin_user'
test/controllers/users_controller_test.rb:48:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:47:in `block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:73:in `admin_user'
test/controllers/users_controller_test.rb:48:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:47:in `block in <class:UsersControllerTest>'
39/39: [==========================================================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.97767s
39 tests, 152 assertions, 0 failures, 1 errors, 0 skips
Note that the admin field was added to the database during a migration, which I understand should automatically produce a boolean admin? method
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean, default: false
end
end
users_controller_test.rb is where the problem apparently resides, specifically in the lines:
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete :destroy, id: #user
...while the complete file looks like this:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should redirect index when not logged in" do
get :index
assert_redirected_to login_url
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when not logged in" do
get :edit, id: #user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect to update when not logged in" do
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: {name: #user.name, email: #user.email }
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete :destroy, id: #user
end
assert_redirected_to login_url
end
test "should redirect destroy when logged in as a non-admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete :destroy, id: #user
end
assert_redirected_to root_url
end
end
and here's the contents of users.yaml
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
admin: true
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
lana:
name: Lana Kane
email: hands#example.gov
password_digest: <%= User.digest('password') %>
mallory:
name: Mallory Archer
email: boss#example.gov
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
Just to add to this. Whilst bf34's answer does the trick it may not be the correct solution.
Currently doing this tutorial and had the same issue. The reason it was purely current_user.admin? is because it shouldn't even reach this check if not logged in.
After a bit of rereading of my code I discovered that I didn't have the before_action of logged_in_user for the destroy method (see second line).
app/controllers/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 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] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
# Handle a successful update.
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
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?
store_location
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
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
from the error message it looks like you're calling admin? on current_user but you don't have anyone logged in, so current_user is nil. Try doing current_user.try(:admin?) instead which will return nil if current_user is also nil.

Rails tutorial 3rd ed. NoMethodError: undefined method `remember_token' for nil:NilClass

i go the problem with test in 9 chapter Rails Tutorial, but problem with test from the 8 chapter. Could anybody help me to solve it?
Problem is here
test "login with remembering" do
log_in_as(#user, remember_me: '1')
assert_not_nil cookies['remember_token']
assert_equal cookies['remember_token'], assigns(:user).remember_token
end
The test says that problem in
NoMethodError: undefined method `remember_token' for nil:NilClass
test/integration/users_login_test.rb:43:in `block in <class:UsersLoginTest>'
test/integration/users_login_test.rb:43:in `block in <class:UsersLoginTest>'
My full user_login_test
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "login with invalid information" do #INVALID
get login_path
assert_template 'sessions/new'
post login_path, session: { email: "", password: "" }
assert_template 'sessions/new'
assert_not flash.empty?
get root_path
assert flash.empty?
end
test "login with valid information followed by logout" do
get login_path
post login_path, session: { email: #user.email, password: 'password' }
assert is_logged_in?
assert_redirected_to #user
follow_redirect!
assert_template 'users/show'
assert_select "a[href=?]", login_path, count: 0
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", user_path(#user)
delete logout_path
assert_not is_logged_in?
assert_redirected_to root_url
# Simulate a user clicking logout in a second window.
delete logout_path
follow_redirect!
assert_select "a[href=?]", login_path
assert_select "a[href=?]", logout_path, count: 0
assert_select "a[href=?]", user_path(#user), count: 0
end
test "login with remembering" do
log_in_as(#user, remember_me: '1')
assert_not_nil cookies['remember_token']
assert_equal cookies['remember_token'], assigns(:user).remember_token
end
test "login without remembering" do
log_in_as(#user, remember_me: '0')
assert_nil cookies['remember_token']
end
end
My user controller is
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] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
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?
store_location
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
All test was green, till i add some code from Chapter 9.2.3 And then i had this problem. Im new in Ruby and its little hard for me solve this problem.
Best regards, and sorry for my english)
The problem is that assigns[:user] is nil. log_in_as is a test helper, it is not calling your controller so assigns is always empty. Also, it is not really testing your controller. You need to write it as the rest of your tests:
test "login with remembering" do
post login_path, session: { email: #user.email, password: 'password', remember_me: '1' }
assert_not_nil cookies['remember_token']
assert_equal cookies['remember_token'], assigns(:user).remember_token
end

Ruby on Rails Tutorial 3rd edition, Chapter 9: Failed test on users_edit_test.rb

I am consistently receiving three errors and I have no idea why. I'm following the tutorial to the best of my ability, and I have scoured through Chapter 9 for mistakes and I haven't seen any. Running bundle exec rake test. I get the three following errors:
FAIL["test_unsuccessful_edit", UsersEditTest, 2015-08-22 09:09:06 +0900]
test_unsuccessful_edit#UsersEditTest (1440202146.96s)
expecting <"users/edit"> but rendering with <[]>
test/integration/users_edit_test.rb:12:in `block in <class:UsersEditTest>'
FAIL["test_successful_edit", UsersEditTest, 2015-08-22 09:09:06 +0900]
test_successful_edit#UsersEditTest (1440202146.97s)
expecting <"users/edit"> but rendering with <[]>
test/integration/users_edit_test.rb:25:in `block in <class:UsersEditTest>'
FAIL["test_successful_edit_with_friendly_forwarding", UsersEditTest, 2015-08-22 09:09:07 +0900]
test_successful_edit_with_friendly_forwarding#UsersEditTest (1440202147.07s)
Expected response to be a redirect to <http://www.example.com/users/762146111/edit> but was a redirect to <http://www.example.com/>.
Expected "http://www.example.com/users/762146111/edit" to be === "http://www.example.com/".
test/integration/users_edit_test.rb:43:in `block in <class:UsersEditTest>'
As you can see, all of my errors can be found in test/integration/users_edit_test. Two of my tests fail in the same way, with this message: expecting <"users/edit"> but rendering with <[]>. Line 12 and 25 has the same code:
assert_template 'users/edit'
Line 43 has the following code:
assert_redirected_to edit_user_path(#user)
I have a _header.html.erb file with a link that is supposed to go to the user's edit page but it just redirects to the index. I have a file app/views/users/edit.html.erb so I don't know why it isn't showing up. Here is the code for the settings link:
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
Here is my code for my users_controller.rb file. I suspect the problem is my correct_user method not firing like it is supposed to. (By the way, I have tried commenting out the code inside the "edit" method, but the problem still persists.)
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 show
#user = User.find(params[:id])
# debugger
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
# #user = User.find(params[:id])
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id].destroy)
flash[:success] = "User deleted"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
def correct_user
#user = User.find(params[:id])
# redirect_to(root_url) unless #user == current_user
redirect_to(root_url) unless #user == current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
In app/helpers/sesions_helper.rb I have two methods, current_user and current_user?
def current_user?(user)
user == current_user
end
def current_user
if(user_id = session[:user_id])
#current_user ||= User.find_by(id: 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
Here is the config/routes file:
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
I suspect the answer to my issue is super easy, but I've no idea what is wrong. Here is the users_edit_test.rb file
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "unsuccessful edit" do
# log_in_as(#user)
get edit_user_path(#user)
log_in_as(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: '',
email: 'foo#invalid',
password: 'foo',
password_confirmation: 'bar' }
assert_template 'users/edit'
end
test "successful edit" do
# log_in_as(#user)
get edit_user_path(#user)
log_in_as(#user)
assert_template 'users/edit'
name = "Foo Bar"
email = "foo#bar.com"
patch user_path(#user), user: { name: name,
email: email,
password: '',
password_confirmation: '' }
assert_not flash.empty?
assert_redirected_to #user
#user.reload
assert_equal #user.name, name
assert_equal #user.email, email
end
test "successful edit with friendly forwarding" do
log_in_as(#user)
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), user: { name: name,
email: email,
password: 'foobar',
password_confirmation: 'foobar' }
assert_not flash.empty?
assert_redirected_to #user
#user.reload
assert_equal #user.name, name
assert_equal #user.email, email
end
end
Although, you did not upload your users_edit_test.rb file here, I actually read the chapter 9 from the book you mentioned and then also got the source code from its github repo.
So, I was running the same test as yours (bundle exec rake test test/integration/users_edit_test.rb) locally and it's passing fine. There is no test failure. But, I figured out that, if the log_in_as(#user) is missing from the test "unsuccessful edit" test, then it fails with the exact same error message that you posted here. And, that makes sense, because, if you don't have log_in_as(#user) i.e. logged_in user, then it can't render the edit page for that user and hence gets this error:
expecting <"users/edit"> but rendering with <[]>
So, I am pretty sure that you have missed that part while typing it from the tutorial.
Here is the full working version (all tests are passing) of the users_edit_test.rbfile:
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "unsuccessful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: "",
email: "user#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), 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
Just copy this and replace your current file's content with this. Then, all tests will pass.
I'm working through this tutorial now as well, and I got the tests to pass just fine, so I'm comparing my tests to yours and you need to make the following changes:
In successful test and unsuccessful test, put log_in_as(#user) before get edit_user_path(#user).
In successful test with friendly forwarding, do just the opposite: put log_in_as(#user) after get edit_user_path(#user).
In your users_controller.rb file, check your private correct_user method:
redirect_to(root_url) unless #user == current_user?(#user)
should be
redirect_to(root_url) unless current_user?(#user)
Making those changes and re-running the test suite should make your tests pass.
Make your users.yml is well defined and there's not a typo over it. I had a typo, and was getting the same error.
Error (notice the upper E in the email)
michael:
name: michael Example
email: michael#Example.com
password_digest: <%= User.digest('password') %>
Well defined
michael:
name: michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
I'm following same tutorial and I got the same error:
expecting <"users/edit"> but rendering with <[]>
I've solved it just with a switch of position of this block:
test "unsuccesful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: "",
email: "invalid#invalid",
password: "foo",
password_confirmation: "bar" }
assert_template 'users/edit'
end
and this one:
test "successful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
name = "Name"
email = "valid#valid.com"
patch user_path(#user), 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
Actually now it works in any order I put the two blocks.. I know it doesn't have any sense but maybe it's linked with some strange behaviour of cut&paste on Cloud9 (the cloud-based IDE which the author suggest to use).
I am working through the tutorial, too. I had some similar issues.
If I understand correctly <[]> indicates a redirect that the test browser hasn't yet followed. I would put a debugger right before the failing assertion and inspect the situation from there. In my case a forgotten follow_redirect! or an assert_template instead of an assert_redirected_to was the reason.
Actually I went into the same problem.
In my case it turned out that I changed the password for the user in the fixture user.yml.
After several hours, I found that there MUST be STRONG alignement between:
user.yml
test_helper.rb2.
the database (where the digest is stored)
If anybody is still having this error i was able to get through it by changing the user in the def setup to another user from the users.yml.

Rails Tutorial by Michael Hartl chapter 9.2.2 errors

I'm new to rails and I'm stuck in chapter 9.2.2 "Requiring the Right User", when I add the 2nd user archer to the users.yml file and add the other code to the user_controller_test.rb and the users_controller.rb, the run bundle exec rake test, I get 30 errors stating that:
ERROR["test_layout_links", SiteLayoutTest, 0.019046]
test_layout_links#SiteLayoutTest (0.02s)
ActiveRecord::StatementInvalid: ActiveRecord::StatementInvalid: SQLite3::SQLException: table users has no column named archer: INSERT INTO "users" ("name", "email", "password_digest", "archer", "created_at", "updated_at", "id") VALUES ('Michael Example', 'michael#example.com', '$2a$04$kDHpg7Zah2wc3X.YbWs5E.pytz8byEkUYo6O7uyPCftblGq3BEogW', '---
name: Sterling Archer
email: duchess#example.gov
password_digest:
users.yml code
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
users_controller_test.rb code
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when not logged in" do
get :edit, id: #user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert flash.empty?
assert_redirected_to root_url
end
end
user_controller.rb code
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] = "Welcome to the Sample Application of the Great Bakerboi!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
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 #user == current_user
end
end
The problem is that you have inadvertently indented the definition of :archer in users.yml.

Resources