我正在构建一个允许用户列出目标的小型网络应用。我希望用户只能编辑自己的内容。我已经有一个身份验证函数作为before_filter,它会检查以确保某人已登录,但它不会检查用户是否是该内容的创建者。我尝试创建第二个名为correct_user的before_filter,其代码如下:
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
为清楚起见,我使用的user_id是101,而我正在尝试编辑的goal_id是31.有人可以解释到底发生了什么吗?
另外,我知道你可以通过使用一个名为CanCan的宝石来解决这个问题(因为类似的问题得到了回答),但有没有办法在不使用宝石的情况下做到这一点?看起来我的简单小功能应该可以工作,但有人可以解释为什么不能这样做吗?
答案 0 :(得分:2)
params
是您的操作发送的所有参数(通过网址或表单字段等)的哈希值。参数的名称(如果存在于URL中)在路径文件中定义。对于你的目标控制器路线,你可能(大概)有:
goals_path: /goals/
goal_path: /goals/:id
edit_goal_path: /goals/:id/edit
因为您收到/goals/31/edit
,params[:id]
为31,即您正在编辑的目标的ID。 correct_user
中的第一行是查找id与params hash(goal_id)中的id匹配的User。所以,你应该做这样的事情:
def correct_user
user = Goal.find(params[:id]).user if params[:id]
redirect_to user_path(current_user) unless current_user?(user)
end
这说,找到有人想要编辑的目标(来自params [:id]),并给我与之关联的用户(你没有发布你的目标模型,我假设目标属于:用户但是你可能已经将其命名为“创建者”或“所有者”。如果用户与登录的当前用户不同,则重定向。您之前的代码试图找到与正在编辑的目标具有相同ID的用户。
答案 1 :(得分:2)
考虑以下假设:
has_many :goals
belongs_to :user
/goals/:id/edit
current_user
)您应该可以像这样访问目标:
def edit
@goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
end
这会将查找范围限定为属于current_user
的目标,因此@goal
将始终属于正确的用户。
答案 2 :(得分:1)
params hash中的参数id是指目标id,而不是用户id。因此,为什么你会看到一个问题。
你想做的事情就像是
def correct_user
@goal = Goal.find(params[:id])
redirect_to(user_path(current_user)) unless current_user?(@goal.user)
end
答案 3 :(得分:0)
其他人回答了你的主要问题,但我想这样说:我强烈建议使用CanCan,即使对于一个非常小的项目。它非常容易使用,它会帮助你很多,你会有很棒的清洁代码
例如,在您的情况下,您可以将此行放在ability.rb
中以管理更新用户的目标
can :update, Goal, :user_id => user.id
并在您的控制器中只需在顶部执行load_and_authorize_resource
。没有手动before_filters,不检查任何条件或类似的东西。
无论你需要在编辑目标时做些什么,比如在索引视图中说,在列出链接时,你只需要输入类似link_to_if(can?(:update, goal) , "edit goal", goal_path(goal) ){}