Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/53.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 阻止其他登录用户访问';编辑';页_Ruby On Rails - Fatal编程技术网

Ruby on rails 阻止其他登录用户访问';编辑';页

Ruby on rails 阻止其他登录用户访问';编辑';页,ruby-on-rails,Ruby On Rails,我正在开发一个小的web应用程序,允许用户列出他们的目标。我希望用户只能编辑自己的内容。我已经有了一个身份验证函数作为before_过滤器,它会检查是否有人登录,但不会检查用户是否是内容的创建者。我尝试创建第二个名为correct\u user的before\u过滤器,其代码如下: def correct_user @user = User.find(params[:id]) redirect_to(user_path(current_user)) unless current_user

我正在开发一个小的web应用程序,允许用户列出他们的目标。我希望用户只能编辑自己的内容。我已经有了一个身份验证函数作为before_过滤器,它会检查是否有人登录,但不会检查用户是否是内容的创建者。我尝试创建第二个名为correct\u user的before\u过滤器,其代码如下:

def correct_user
  @user = User.find(params[:id])
  redirect_to(user_path(current_user)) unless current_user?(@user)
end 
此外,这里是运行get请求编辑我自己的内容的服务器输出

Started GET "/goals/31/edit" for 127.0.0.1 at 2011-05-18 15:22:38 -0400
  Processing by GoalsController#edit as HTML
  Parameters: {"id"=>"31"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE ("users"."id" = 101) LIMIT 1
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE ("users"."id" = 31) LIMIT 1
Redirected to http://localhost:3000/users/101 Completed 302 Found in 49ms
Completed 302 Found in 49ms
为了清楚起见,我使用的用户id是101,我试图编辑的目标id是31。有人能解释一下到底发生了什么事吗


另外,我知道你可以通过使用一个名为CanCan的gem来解决这个问题(关于这个问题也回答了一个类似的问题),但是有没有一种不用gem的方法呢?看起来我的简单小函数应该可以工作,但是有人能解释一下为什么它不能工作吗?

params
是所有发送到操作的参数(通过url或表单字段等)的散列。参数的名称(如果存在于URL中)在路由文件中定义。对于您的目标控制器路线,您可能(大概)有:

因为您正在获取
/goals/31/edit
参数[:id]
是31,即您正在编辑的目标的id。
correct_user
中的第一行是在params散列(goal_id)中查找id与id匹配的用户。所以说真的,你应该这样做:

def correct_user
  user = Goal.find(params[:id]).user if params[:id]
  redirect_to user_path(current_user) unless current_user?(user)
end
def edit
  @goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
end

这就是说,找到某人想要编辑的目标(从params[:id]),并给我与其关联的用户(您没有发布您的目标模型,我假设目标属于:user,但您可能将其命名为“creator”或“owner”)。如果用户与当前登录的用户不同,则重定向。您以前的代码试图查找与正在编辑的目标具有相同id的用户。

参数哈希中的参数id指的是目标id,而不是用户id。因此,您会看到问题

很可能你想做的是

def correct_user
   @goal = Goal.find(params[:id])
   redirect_to(user_path(current_user)) unless current_user?(@goal.user)
end

鉴于以下假设:

  • 用户模型:
    有许多目标
  • 目标模型:
    属于用户
  • 编辑目标的路线:
    /goals/:id/edit
  • 目标控制器,编辑操作已通过身份验证(因此您肯定会有一个
    当前用户
  • 您应该能够像这样访问目标:

    def correct_user
      user = Goal.find(params[:id]).user if params[:id]
      redirect_to user_path(current_user) unless current_user?(user)
    end
    
    def edit
      @goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
    end
    

    这将把查找范围扩大到属于
    当前用户的目标,因此
    @goal
    将始终属于正确的用户。

    其他人回答了您的主要问题,但我想说的是:我强烈建议使用CanCan,即使是非常小的项目。它非常容易使用,并且对您有很大帮助,而且您将拥有非常棒的干净代码

    例如,在您的情况下,您可以将这一行放在
    ability.rb
    中,以管理更新用户的目标

    can:update,Goal,:user\u id=>user.id

    在您的控制器中,只需在顶部执行一个
    加载和授权资源。在过滤前不需要手动操作,不需要检查任何条件或类似情况


    无论你在什么地方需要输入一些关于编辑目标的信息,比如说在索引视图中,当列出链接时,你只需要输入一些类似于
    link\u to\u if(can?(:update,goal),“edit goal”,goal\u path(goal)){}

    @goal=User.find
    ?那里可能有个打字错误!:)这就把事情弄清楚了,谢谢你!但是为什么在第一行末尾附加“if params[:id]”呢?不使用它的后果是什么?取决于您如何定义前过滤器。如果before筛选器在每个操作上运行,它将在收集操作(索引,新建)上引发RecordNotFound异常。如果您的before过滤器只在编辑、更新、销毁、创建之前运行,那么可能就没有必要了。基本上,如果第一行在params散列中找不到id,它就不会执行,而不是执行并抛出异常。再次感谢!