【问题标题】:Ruby on Rails Tutorial Chapter 10 Exercise RSpec FailuresRuby on Rails 教程第 10 章练习 RSpec 失败
【发布时间】:2011-06-29 19:33:21
【问题描述】:

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

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'”错误(如下所示):

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 中使用。

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 来“查找”用户。

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

  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

任何帮助将不胜感激!

【问题讨论】:

  • 好问题,感谢分享测试代码。我发现flash测试没有任何作用--你需要添加.should:flash[:notice].should =~ /cannot delete yourself/
  • 现在才看到这条评论。谢谢。

标签: ruby-on-rails ruby-on-rails-3 rspec-rails


【解决方案1】:

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

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

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

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

【讨论】:

  • 所以通过@user.id(或@admin.id,在引用的地方)工作!所以我猜RSpec没有正确提取id。有趣的。感谢您的帮助!
  • @Dylan,比较用户对象与仅比较用户 ID 是否更安全?在这种情况下,您通常无论如何都需要该对象来进行 .destroy,因此执行 User.find 似乎并不像“浪费”。只是想知道是否应该在对象或 ID 级别进行身份比较。
  • @Mark 至少在这种情况下,我倾向于在删除调用中使用id,因为这就是它在实际 HTTP 请求中的传递方式。至于比较current_user == @user,实际上执行if current_user.id == params[:id] 的工作量可能更小,就好像评估结果为真一样,@user 对象实际上并不需要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多