2011-10-26 1 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 사진, 내 사진 인덱스보기에서는 모든 사용자의 사진을 나열하고 사용자가 하나의 사진을 프로필 사진으로 설정할 수 있습니다. 사용자 테이블은이 ID를 개최, primary_photo_id라는 열이 있고, 나는 이것을 설정하는 LINK_TO를 사용

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

문제는 @user가 그 때문에의 before_filter 차기가 작동이되지 않도록하는 것입니다 params [: id]를 통해 검색하면 올바른 params가 아니기 때문에 실패합니다. before_filter를 제거하면 정상적으로 작동하지만 더 이상 올바른 사용자를 확인하지 않습니다. 위의 코드가 작동하지만,이 하나의 이유

은 (두 번째 다소 관련된 질문은 다음과 같습니다..

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

하지 않는

덕분에 나는 레일 꽤 새로운 해요 및 프로그래밍 아무것도 할 수 있도록 내 특정 질문 및 여기에있는 코드로 수행하고있는 나쁜 습관에 대해 매우 많이 감사드립니다.

답변

2

before 필터 (#correct_user)는 #update 전에 실행되므로 인스턴스 변수 @user은 아직 설정되지 않았습니다. 먼저 다른 필터에서 필터를 설정하지 않은 경우 필터에서 비교합니다. 귀하의 실행 순서는 다음과 같습니다

  1. 실행 #correct_user-@user에 CURRENT_USER 비교 (설정되지 않은 경우,이 전무하다). 이들은 오직 당신의 문제가 단지이다 해결하기 위해 가장 쉬운 방법은 사용자가 나는 우리가 그것을 통해 가정
  2. 같은데요 로그인하지 않은 경우와 일치, 실행 #UPDATE 및 아마

@user을 볼 것이다 전과 필터로 @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 

이제 필터에 위치되고, 컨트롤러 액션의 각 다시 찾아 볼 필요가 없다. 희망이 도움이!

+0

위대한 작품. 감사합니다 매트! 실제로 두 개의 before_filters (첫 번째는 get_user, 다른 하나는 올바른 사용자를 확인)를 사용하기로 결정했습니다. 아마 "건조한"덜 아마 비록 나에게 조금 더 분명 읽습니다. user = user.find (params [: id])를 사용하는 대신, user = current_user도 할 수 있습니다 (세션 사용자를 도우려는 도우미 메소드가 있기 때문에). 일반적으로 권장됩니다. , 그리고 로그인 한 사용자 외에는 다른 사람이 할 수없는 다른 일들이 있습니까? – kindofgreat

+0

그래, 그런 종류의 조건에 대해 필자는 필자의 필터를 설정하여 사용자가 관리자인지 확인한 다음 params 또는 로그인 한 사용자에게 하드 와이어로 설정하도록 허용합니다. '@user = current_user.admin과 같은 것? ? User.find (params [: id]) : current_user'. admin 사례가없는 경우 사용자 객체가 이미 인스턴스화되어 있고 다른 조회를 수행 할 필요가 없으므로 admin_case에 직접 설정해야합니다. –

관련 문제