Ruby on Rails 教程第 10 章练习 RSpec 失败 [英] Ruby on Rails Tutorial Chapter 10 Exercise RSpec Failures
问题描述
我正在做 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屋!