Ruby on Rails语法

这是你知道如果你知道答案就会让你觉得愚蠢的问题之一,但我不能让这件事情起作用,所以这里就是这样。 在railstutorial.org中我试图解决第10章末尾的练习5,但下面的代码有问题,我尝试的每个变体(例如使用’除’)都不起作用。 如果当前用户不是管理员用户,我只想执行两行代码。 我哪里错了?

def destroy if !current_user.admin? User.find(params[:id]).destroy flash[:success] = "User destroyed." end redirect_to users_path end 

编辑:我让当前用户与要删除的用户混淆。 我正在使用Aditya的代码,我确信它是正确的,但现在我收到一条“无法运行测试”的消息,表明我的测试中存在语法错误(如下)。

 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 not allow an admin user to destroy himself" do lambda do delete :destroy, :id => admin end.should_not change(User, :count) end end 

 def destroy if current_user.admin? # If the current user IS admin User.find(params[:id]).destroy # Find the user and destroy it flash[:success] = "User destroyed." # Set the flash end redirect_to users_path # Go to users. end 

你的if条件没有意义。 它说如果用户不是管理员,则销毁。 虽然我认为只有管理员可以摧毁用户。 🙂

编辑:在阅读了Railstutorial.org第10章练习5后,我得到了一个更清晰的想法。 :)修改销毁操作以防止管理员用户破坏自己。

我知道这可能是作弊,但这是如此,我们的吸盘在这里提供帮助!

 def destroy user = User.find(params[:id]) if user != current_user user.destroy flash[:notice] = "User destroyed". else flash[:error] = "Suicide is immoral." end redirect_to users_path end 

另一个编辑,只有管理员不允许落在剑上。

 def destroy user = User.find(params[:id]) # Find the victim if (user == current_user) && (current_user.admin?) flash[:error] = "Suicide is immoral." else user.destroy flash[:notice] = "User destroyed". end redirect_to users_path end 

究竟什么不起作用?

检查用户是否存在您传递的id参数。 如果找不到具有给定id的用户,则User.find返回nil。 在nil上调用destroy会抛出错误。

既然你编写的代码做了你认为它做的,那么错误是在User#admin? 。 要检查它,请打开rails console并手动查找当前用户。 它真的是一个管理员,数据库说什么? 致电admin? 手工,看看它返回了什么。 如果用户是根据数据库管理员,那么错误是在执行admin? -方法。

关于OP的编辑,包括rspec测试,’admin’变量不应该是本地的,而是实例变量(@admin):

 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 not destroy himself" do lambda do delete :destroy, :id => @admin end.should_not change(User, :count) end end 

此外,我对控制器的代码进行了一些其他修改:

 ... before_filter :authenticate_admin, :only => :destroy ... def destroy user = User.find(params[:id]) if user != current_user user.destroy flash[:success] = t(:user_deleted_message) else flash[:error] = t(:user_not_deleted_message) end redirect_to users_path end ... private def authenticate_admin if current_user.nil? redirect_to(signin_path) else redirect_to(root_path) unless current_user.admin? end end ... 

我希望它可以帮助其他人从教程中寻找练习的解决方案。

我问了同样的问题。 我用了

 def destroy User.find(params[:id]).destroy unless current_user.admin? flash[:success] = "User destroyed." redirect_to users_path end 

有点时髦,但它很短!