2012-02-04 13 views
5

「ロール」の表から検索することで、ユーザーが正確に何ができるのかを判断する大容量ファイルがあります。各ロールは、プロジェクトを追加したり、主要な会社のレコードを編集することができるなど、特定のユーザーが実行できるものに対応しています。現時点でcancanのability.rbの負荷を減らす

load_and_authorize_resourceを実行するすべてのコントローラのアクションのような> 30個の文を通過:それも何かを行う前に、サーバが> 30個のクエリを実行されているため

ability.rb (>30 times) 
Role.where("user_id = ? AND role = ? AND roleable_type = ? AND roleable_id IS NULL", user.id, "delete", "task").last.present? ? (can :destroy, Task) : nil 

これは恐ろしく非効率的なソリューションです。

これを行う最良の方法は、コントローラとビューに必要なものに基づいて実行する必要があるクエリを実行することだけです。これを行う方法はありますか?

+0

私は自分のcancanの使用状況を監査する必要があります。好奇心のために、それは開発環境と本番環境の両方でそれをしますか? – miked

+0

あなたの団体で、すべてのことがその1つの行で起こっていることを私が突き止めるのは難しいです。しかしおそらく、あなたは 'User.includes(:roles).find(@ user.id)'のようなものでユーザーの役割のすべてを読み込むことができます。次に、1つのSQLクエリが処理するためにユーザーのロールをメモリに保持します。 – danneu

+0

@danneu - 私はあなたの提案を試し、クエリの数を減らすかどうかを見ていきます。基本的に、各「役割」はユーザーに特定の権限を与えます。これにより、ユーザーの能力を無限にカスタマイズすることができます(ただし、見ての通り、 – sscirrus

答えて

4

これは、部分的にあなたが役割テストを書いた方法です。代わりに、書き込みの> 30回:

Role.where("user_id = ? AND role = ? AND roleable_type = ? AND roleable_id IS NULL", user.id, "delete", "task").last.present? ? (can :destroy, Task) : nil 

あなたが代わりに一度、ユーザーの役割のすべてを照会することができます

@user_roles = user.roles.all 

が続いて個別にそれぞれの役割をテスト :すべてのため

can :destroy, Task if @user_roles.detect {|u| u["role"] == "delete" && u["roleable_type"]=="task" } 

ロールは1つのクエリでメモリに読み込まれますが、30のクエリはありません。

+0

可変キャッシング。確かに。 cancanだけではない.. – pduersteler