Hartl Rails教程Ch9,“test_should_redirect_destroy_when_not_logged_in”错误?

时间:2016-03-10 01:38:24

标签: ruby-on-rails ruby railstutorial.org

通过Hartl的教程,在第9章,代码清单9.56中产生了以下错误,显示'admin?'作为一种未定义的方法。

我已检查(并重新检查)自上次绿色测试后已修改的2段代码。难住了。

 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

请注意,迁移期间管理员字段已添加到数据库中,我理解应该自动生成布尔管理员?方法

class AddAdminToUsers < ActiveRecord::Migration
  def change
    add_column :users, :admin, :boolean, default: false
  end
end

users_controller_test.rb是问题显然存在的地方,具体如下:

test "should redirect destroy when not logged in" do
  assert_no_difference 'User.count' do
  delete :destroy, id: @user

...虽然完整的文件如下所示:

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

这是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 %>

2 个答案:

答案 0 :(得分:1)

只是添加到此。虽然bf34的答案可行,但它可能不是正确的解决方案。

目前正在执行本教程并遇到同样的问题。它纯粹是current_user.admin的原因?是因为如果没有登录,它甚至不应该达到此检查。

在重新阅读我的代码后,我发现我没有使用destroy_in_user的before_action作为destroy方法(参见第二行)。

<强> 应用程序/控制器/ 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

答案 1 :(得分:0)

来自错误消息,您似乎在admin?上呼叫current_user,但您没有任何人登录,因此current_user为零。尝试执行current_user.try(:admin?),如果current_user也是nil,则返回nil。