Ruby on rails RubyonRails教程第10章练习RSpec失败
我正在做Rails教程第10章中的练习,但遇到了一个问题,这让我确保管理员用户不能删除自己。我最初的想法是简单地检查当前用户的id,并将其与params[:id]进行比较,以确保它们不相等。我的用户控制器中的销毁操作如下所示:Ruby on rails RubyonRails教程第10章练习RSpec失败,ruby-on-rails,ruby-on-rails-3,rspec-rails,Ruby On Rails,Ruby On Rails 3,Rspec Rails,我正在做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]
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
@user = User.find(params[:id])
if current_user == @user
flash[:notice] = "You cannot delete yourself."
else
@user.destroy
flash[:success] = "User destroyed."
end
当我在应用程序中手动测试它时,这非常有效,但我的3个RSpec测试失败,出现了相同的“undefined method”to_I'”错误(如下所示):
为什么RSpec中使用“to_i”方法会出现问题?如果有人想知道我是否倾向于这种方法,因为我认为最好是将当前用户id与要删除的用户id进行比较(通过params[:id]),而不是点击数据库“查找”用户
作为参考,这是我的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
任何帮助都将不胜感激 在您的规范中,尝试在
:id
参数上使用@user.id
而不是@user
(我知道教程中说只使用@user
,但在未正确提取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
@user = User.find(params[:id])
if current_user == @user
flash[:notice] = "You cannot delete yourself."
else
@user.destroy
flash[:success] = "User destroyed."
end
在您的规范中,尝试在
:id
参数上使用@user.id
而不是@user
(我知道教程中说只使用@user
,但可能在未正确提取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
@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级别进行身份比较的一般规则。@至少在这种情况下,标记,我倾向于在delete调用中使用
id
,因为这是在实际的HTTP请求中传递它的方式。就比较current\u user==@user
而言,如果current\u user.id==params[:id],那么实际上要做的工作量可能会少一些,因为如果该值为true,那么实际上根本不需要@user
对象。因此传递@user.id(或@admin.id,在引用的地方)是有效的!所以我猜RSpec没有正确提取id。很有趣。谢谢你的帮助@Dylan,比较用户对象和用户ID更安全吗?在这种情况下,您通常需要在.destroy中使用该对象,因此执行User.find似乎不是一种“浪费”。只是想知道是否有一个关于是否应该在对象或ID级别进行身份比较的一般规则。@至少在这种情况下,标记,我倾向于在delete调用中使用id
,因为这是在实际的HTTP请求中传递它的方式。至于比较current\u user==@user
,如果current\u user.id==params[:id],那么实际上要做的工作量可能会更小,因为如果这一计算结果为真,那么就永远不需要@user
对象。问得好,谢谢分享测试代码。我发现flash测试没有任何作用——你需要添加。should
:flash[:注意]。should=~/不能删除你自己/
刚刚看到这个评论。谢谢。好问题,谢谢分享测试代码。我发现flash测试没有任何作用——你需要添加。should
:flash[:注意]。should=~/不能删除你自己/
刚刚看到这个评论。谢谢