Ruby on Rails 教程第 10 章练习 RSpec 失败 [英] Ruby on Rails Tutorial Chapter 10 Exercise RSpec Failures

查看:52
本文介绍了Ruby on Rails 教程第 10 章练习 RSpec 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做 Rails 教程第 10 章中的练习,但在练习中遇到了障碍,该练习让我确保管理员用户不能删除自己.我最初的想法是简单地检查当前用户的 id 并将其与 params[:id] 进行比较以确保它们不相等.我的用户控制器中的销毁操作如下所示:

I'm working on the exercises from Chapter 10 of the Rails Tutorial and ran in to a snag with the exercise that has me ensure that an admin user can't delete themselves. My initial idea was to simply check the id of the current user and compare it against params[:id] to make sure that they're not equal. My destroy action in my Users controller looked like this:

def destroy
  if current_user.id == params[:id].to_i
    flash[:notice] = "You cannot delete yourself."
  else
    User.find(params[:id]).destroy
    flash[:success] = "User destroyed."
  end
  redirect_to users_path
end

当我在应用程序中手动测试时,这非常有效,但我的 3 个 RSpec 测试失败并出现相同的未定义方法‘to_i’"错误(如下所示):

This works perfectly when I test it manually in the app but 3 of my RSpec tests fail with the same "undefined method 'to_i'" error (as seen below):

1) UsersController DELETE 'destroy' as an admin user should destory the user
   Failure/Error: delete :destroy, :id => @user
     NoMethodError:
       undefined method `to_i' for #<User:0x000001032de188>
   # ./app/controllers/users_controller.rb:48:in `destroy'
   # ./spec/controllers/users_controller_spec.rb:310:in `block (5 levels) in <top (required)>'
   # ./spec/controllers/users_controller_spec.rb:309:in `block (4 levels) in <top (required)>'

2) UsersController DELETE 'destroy' as an admin user should redirect to the users page
   Failure/Error: delete :destroy, :id => @user
     NoMethodError:
       undefined method `to_i' for #<User:0x000001032b5850>
   # ./app/controllers/users_controller.rb:48:in `destroy'
   # ./spec/controllers/users_controller_spec.rb:315:in `block (4 levels) in <top (required)>'

3) UsersController DELETE 'destroy' as an admin user should not allow you to destroy self
   Failure/Error: delete :destroy, :id => @admin
     NoMethodError:
       undefined method `to_i' for #<User:0x0000010327e350>
   # ./app/controllers/users_controller.rb:48:in `destroy'
   # ./spec/controllers/users_controller_spec.rb:321:in `block (5 levels) in <top (required)>'
   # ./spec/controllers/users_controller_spec.rb:320:in `block (4 levels) in <top (required)>'

如果我使用 params[:id] 来查找用户并将其与 current_user 进行比较,如下所示,那么它在应用程序和 RSpec 中都有效.

If I use the params[:id] to find the user and compare it to the current_user like I have below then it works both in the app and in RSpec.

def destroy
  if current_user == User.find(params[:id])
    flash[:notice] = "You cannot delete yourself."
  else
    User.find(params[:id]).destroy
    flash[:success] = "User destroyed."
  end
  redirect_to users_path
end

为什么 RSpec 中的to_i"方法会出现问题?如果有人想知道我倾向于这种方法,因为我认为最好简单地将当前用户 ID 与要删除的用户 ID(通过 params[:id])进行比较,而不是点击 db 来查找"用户.

Why would there be a problem in RSpec with the "to_i" method? If anyone is wondering I was leaning toward that approach because I thought it would best to simply compare the current user id to the id of the user targeted for deletion (via the params[:id]) instead of hitting the db to "find" the user.

作为参考,这是我的 RSpec 测试:

For reference this is my RSpec test:

  describe "DELETE 'destroy'" do
    before(:each) do
        @user = Factory(:user)
    end 

    ...

    describe "as an admin user" do
      before(:each) do
        @admin = Factory(:user, :email => "admin@example.com", :admin => true)
        test_sign_in(@admin)
      end

      it "should destory the user" do
        lambda do
          delete :destroy, :id => @user
        end.should change(User, :count).by(-1)
      end

      it "should redirect to the users page" do
        delete :destroy, :id => @user
        response.should redirect_to(users_path)
      end

      it "should not allow you to destroy self" do
        lambda do
          delete :destroy, :id => @admin
        end.should change(User, :count).by(0)
        response.should redirect_to(users_path)
        flash[:notice].should =~ /cannot delete yourself/
      end
    end
  end

任何帮助将不胜感激!

推荐答案

在您的规范中,尝试在您的 上使用 @user.id 而不是 @user:id 参数(我意识到教程说只使用 @user,但在 id 没有被正确提取的地方可能会发生一些事情):

In your specs, try using @user.id instead of @user on your :id parameter (I realize the Tutorial says to just use @user, but something may be going on where the id isn't being properly extracted):

delete :destroy, :id => @user.id

但你可以考虑重组为这样的:

But you may consider restructuring to something like this:

@user = User.find(params[:id])
if current_user == @user
  flash[:notice] = "You cannot delete yourself."
else
  @user.destroy
  flash[:success] = "User destroyed."
end

这篇关于Ruby on Rails 教程第 10 章练习 RSpec 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆