2011-08-15 19 views
0

が "編集可能"で他の多くのクラスが "編集可能"であるedit_privilegesと呼ばれるレールアプリケーションに関係テーブルがあります。これらのクラスのうちの2つがMessageCommentであるとします。Railsの多相関係テーブルクエリ - 複数のオブジェクトを検索

マイEditPrivilegeモデルは、次のコードを使用しています。ユーザーは、特定のモデルの編集権限を持っているかどうかを決定するために

belongs_to :editor, :class_name => "User" 
belongs_to :editable, :polymorphic => true 

そしてUser、当然の

has_many :edit_privileges, :foreign_key => "editor_id" 

を、私はできません

user.edit_privileges.find_by_editable_id(@message.id) 

この場合、ユーザーha同じ編集者IDの編集権限を@messageとすると、そのテーブルから間違った編集権レコードを含む真を返します。

だから、私は、これらのオプションをやってみました:

user.edit_privileges.find(:all, :conditions => ["editable_id = ? AND editable_type ?", @message.id, @message.class.to_s]) 
user.edit_privileges.where(:editable_id => @message.id, :editable_type => @message.class.to_s) 

右のレコードを見つけることで素晴らしい作品が、(何の編集権限がない場合は空の配列[])の代わりに、オブジェクトの配列を返します。 .destroyを配列に渡すことができないので、編集権限を破棄するメソッドを作成しようとすると、これは特に問題になります。

上記の2つのソリューションに.firstを追加すると、最初のオブジェクトが返され、クエリの結果が空の場合はnilが返されますが、それを行うには本当に最適な方法ですか?このようにすることに何か問題はありますか? (のような、代わりにfind_by_editabe_id_and_editable_typeのような動的な属性ベースのファインダーを使用しての)

+1

[]は、ハッシュが、配列ではありません。配列のすべてのレコードを破棄する場合など、配列(コレクション)に対してバッチ処理を実行する場合は、 'users.map(&:destroy)'を使用できます。 –

答えて

3

利用find(:first, ...)代わりのfind(:all, ...)は、一つのレコードを(RecordNotFoundの例外が発生します見つけながら、nilを返すことがあります、それを注意してください)を取得します。だからあなたの例:

user.edit_privileges.find(:first, :conditions => { :editable_id => @message.id, :editable_type => @message.class.to_s }) 

ところで、あなたはより多くのエッジレールのバージョン(3.xの)にしている場合、Model.where(...).firstは新しい構文は次のとおりです。

user.edit_privileges.where(:editable_id => @message.id, :editable_type => @message.class.to_s).first 
+0

私はこれをやる方法だと思っていましたが、配列から最初のレコードを抜き出すことは私には奇妙に思えるので、私は気をつけなければならない別の「ベストプラクティス」があるかどうかはわかりませんでした。 –

+0

これは、 'find_by_editabe_id_and_editable_type'のような動的属性ベースのファインダを使うよりも望ましい理由はありますか? –

+1

find_by_this_and_thatはきれいでダイナミックな方法ですが、より多くの条件が使用される場合は、 'どこで(...)。first 'を使用する方が柔軟性があります。 –

関連する問題