我在某些操作上运行了一个before_filter来检查用户是否是current_user。
before_filter :correct_user, :only => [:edit, :update, :destroy]
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
redirect_to current_user, :notice => "User updated!"
else
redirect_to current_user, :notice => "User not updated. waa waa."
end
end
private
def correct_user
if current_user != @user
redirect_to root_url, :notice => "Cannot act on different user."
end
end
不确定这是否是最好的做事方式,但它有效(也许更好的做法是简单地使用current_user而不是通过params找到@user?)
现在用户有很多照片,在我的照片索引视图中,我列出了所有用户的照片,并允许用户将任何一张照片设置为个人资料照片。用户表有一个名为primary_photo_id的列,用于保存此ID,我使用link_to来设置它:
=link_to "Make this your profile photo", user_path(@user, :user => {:primary_photo_id => "#{photo.id}"}), :method => :put
问题是before_filter启动并将阻止它工作,因为通过params [:id]检索的@user失败,因为它不是正确的参数。如果我删除了before_filter,它工作正常,但它不再检查正确的用户了。
(第二个有点相关的问题是为什么上面的代码可以工作但是这个:
=link_to "Make this your profile photo", user_path(@user, :primary_photo_id => "#{photo.id}"), :method => :put
不
感谢。我对rails和编程很陌生,所以你可以对我的具体问题说些什么,以及我在这里用代码做的任何不好的做法,都非常感激。
答案 0 :(得分:2)
之前的过滤器(#correct_user
)在#update
之前运行,因此如果您未在过滤器中进行比较,则尚未设置实例变量@user
在过滤器之前的另一个您的执行顺序如下:
#correct_user
- 将current_user与@user
进行比较(如果未设置,则为nil)。如果用户没有登录,那么这些只会匹配我在猜测@user
解决问题的最简单方法可能就是将@user
查询移到之前的过滤器中:
before_filter :correct_user, :only => [:edit, :update, :destroy]
def edit
# .. as before, but no need to look up user first
end
def update
if @user.update_attributes(params[:user])
redirect_to current_user, :notice => "User updated!"
else
redirect_to current_user, :notice => "User not updated. waa waa."
end
end
def destroy
# .. as before, but no need to look up user first
end
private
def correct_user
@user = User.find(params[:id])
if current_user != @user
redirect_to root_url, :notice => "Cannot act on different user."
end
end
由于@user
现在位于过滤器中,因此无需在每个控制器操作中再次查找它。希望这有帮助!