Ruby on Rails语法

时间:2010-12-22 14:32:08

标签: ruby-on-rails ruby

这是你知道如果你知道答案就会让你觉得愚蠢的问题之一,但我不能让这件事情起作用,所以这里就是这样。在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

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:0)

究竟什么不起作用?

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

答案 2 :(得分:0)

由于您编写的代码执行了您认为的操作,因此错误位于User#admin?。 要进行检查,请打开rails console并手动查找当前用户。它真的是一个管理员,数据库说什么?手动调用admin?并查看它返回的内容。如果用户是根据数据库的admin,那么错误就在admin? - 方法的实现中。

答案 3 :(得分:0)

关于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
...

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

答案 4 :(得分:0)

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

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

    end
有点时髦,但很简短!