我正在从Rails Tutorial的第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
当我在应用程序中手动测试它时,这非常有效,但是我的RSpec测试中有3个失败并出现相同的“未定义方法'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进行比较,就像我在下面那样,那么它在app和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命中为“find”用户。
作为参考,这是我的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
任何帮助将不胜感激!
答案 0 :(得分:1)
在您的规范中,尝试在@user.id
参数上使用@user
而不是:id
(我意识到教程说只使用@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