2011-10-26 29 views
0

访问仅当我运行上的一些动作一的before_filter,以检查是否该用户是CURRENT_USER。绕过的before_filter但是从不同的控制器/视图

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 

不知道这是做事情的最好方法,但它的工作原理(也许更好的做法是简单地使用,而不是通过PARAMS发现@user CURRENT_USER?)

现在用户的has_many照片,并在我的照片索引视图中列出所有用户的照片,并允许用户将任何一张照片设置为个人资料照片。用户表有一个称为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会阻止这样做,因为@user是通过params [:id]检索失败,因为它不是正确的参数。如果我删除了before_filter,它工作正常,但它不再检查正确的用户。

(第二有点相关的问题是,为什么上面的代码工作,但此一:。

=link_to "Make this your profile photo", user_path(@user, :primary_photo_id => "#{photo.id}"), :method => :put 

谢谢,我很新的轨道和程序,所以,只要你能说关于我的具体问题,任何不好的做法,我在这里的代码做的,是非常赞赏。

回答

2

过滤器(#correct_user)上运行的前#update之前,让你的实例变量@user尚未设定时如果在第一次过滤之前没有将其设置在另一个过滤器中,则将它与过滤器进行比较。你的执行顺序是这样的:

  1. 运行#correct_user - 比较CURRENT_USER到@user(如果未设置,这是无)。这些将只匹配,如果用户没有我猜
  2. 假设我们把它通过登录,运行#UPDATE并期待@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现在正在位于过滤器,也没有必要在每个控制器的行动再次查找。希望这可以帮助!

+0

这个伟大的工作。谢谢马特!我实际上决定使用两个before_filters,第一个用于get_user,另一个用于检查用户是否正确。尽管它可能不那么“干燥”,但对我来说有点清晰。而不是使用用户= User.find(PARAMS [:编号]),我也可以做用户= CURRENT_USER(因为有一个辅助方法来获取会话的用户)..这是一般建议,特别是对,比方说,编辑,更新,以及其他任何人都无法做到的事情,除了登录用户? – kindofgreat

+0

是啊,频繁的那种状态,我会成立之前,我的过滤器,这样就计算出,如果用户是管理员,如果这样将允许来自PARAMS设置,否则硬线连接到登录的用户。就像'@user = current_user.admin? ? User.find(params [:id]):current_user'。 如果您没有管理的情况下,我只是将它设置为直接CURRENT_USER,因为你可能已经有一个用户对象实例化,这样做的另一个查询是没有意义的。 –

相关问题