0

cancanを使用して、アプリの包括的な権限システムを構築しています。モデルに:readまたは:manage権限が設定されている場合でも、特定のレコードを「除外」できる必要があります。

can :read , User

しかし、特定のIDを除外する必要があります...次のようなものです。

can :read, User except when id in (1,2,3,.... list_of_excluded_ids)

次のようにlist_of_excluded_idsを作成して、これを機能させようとしました。

all_ids = User.all
excluded_ids = Excluded.all (This model stores excluded ids)
permitted_id = all_ids - excluded_ids

次に、このリストを使用して、各IDの権限を設定することを繰り返します

permitted_ids.each do |permitted_id|
can :read, User, :id => permitted_id
end

このメソッドは、すべてのIDのリストが小さい場合に機能します。リストが大きい場合、次のようなORを使用して非常に長いSQLクエリを生成するため、メモリエラーでmysqlをカーシングします。

SELECT `users`.* FROM `users` WHERE ((`users`.`id` = 271) OR ((`users`.`id` = 270) OR ((`users`.`id` = 269) OR ((`users`.`id` = 268) OR ((`users`.`id` = 267) OR ((`users`.`id` = 266) OR ((`users`.`id` = 265) OR ((`users`.`id` = 264) OR ((`users`.`id` = 263) OR .....))))))

上記のクエリは、たとえば、クエリ全体をここに投稿できないためです。このクエリは非常に大きくなるため、mysqlがクラッシュします。どんな助けでも大歓迎です。

4

1 に答える 1

0

アビリティにスコープを渡すことができます:

can :read, User, User.where(id => permitted_ids) do |u|
  permitted_ids.include? u.id
end

が配列であると仮定するpermitted_idsと、これは SQL の "IN" 句を使用して、ユーザーのインデックス アクションのスコープを設定します。show アクションの場合、CanCan はブロックを使用して、アクセスされているユーザーを渡します。ブロックとスコープは同じことを行うことに注意してください。これはばかげているように思えますが、CanCan では、show アクションに使用するスコープを使用するときにブロックを提供する必要があります。

于 2013-03-18T20:19:04.627 に答える