2011-10-26 3 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 

ない、

今すぐユーザーhas_manyの写真(多分単に代わりのparamsを経由して@userを見つけるのCURRENT_USERを使用するより良い練習ですか?)これは、物事を行うための最善の方法ですが、それが動作するかどうか確認してください私の写真のインデックスビューでは、私はすべてのユーザーの写真を一覧表示し、ユーザーがいずれかの写真をプロフィール写真として設定できるようにします。ユーザテーブルには、この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を削除してもうまくいきますが、正しいユーザーをチェックしていません。

(第2やや関連する質問は、上記のコードが動作する理由ですが、この1:

=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を比較する(未設定の場合、これがnilです)。ユーザーは、私はおそらくあなたの問題を解決する最も簡単な方法は、ちょうどにあり、我々はそれを介して行わ想定し
  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

これはうまくいった。マットありがとう!実際には2つのbefore_filtersを使用することにしました。最初はget_userに、もう1つは正しいユーザーをチェックするためです。おそらくあまり「乾いていない」とは思えますが、私には少しはっきりしています。 user = user.find(params [:id])を使用する代わりに、私はuser = current_userを実行することもできます(セッションのユーザーを取得するヘルパーメソッドがあるので)。他の誰かがログインできるユーザー以外は実行できないはずのものはありますか? – kindofgreat

+0

ええ、この種の状態では、ユーザーが管理者であるかどうかを判断し、そうでなければログインしたユーザーにハードワイヤーを設定することができるように、フィルターを設定します。 '@user = current_user.adminのようなもの? ? User.find(params [:id]):current_user'です。 管理者のケースがない場合は、ユーザーオブジェクトがインスタンス化されている可能性があり、別の参照を行うことがないため、current_userに直接設定します。 –

関連する問題