5

'롤 (Roles)'테이블에서 검색하여 정확히 사용자가 수행 할 수있는 작업을 결정하는 큰 능력 파일이 있습니다. 각 역할은 특정 사용자가 수행 할 수있는 작업 (예 : 프로젝트를 추가하거나 주요 회사 레코드를 편집 할 수있는 작업)에 해당합니다. 그것도 아무것도 수행하기 전에 서버가> (30 개) 쿼리를 실행하기 때문이 끔찍하게 비효율적 인 솔루션입니다cancan에서 ability.rb의로드를 줄입니다.

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 

: 순간

load_and_authorize_resource을 실행하는 모든 컨트롤러 액션 같은 30>을 통해 문을 간다.

이 작업을 수행하는 가장 좋은 방법은 컨트롤러 및보기에 필요한 쿼리를 기반으로 실행해야하는 쿼리를 실행하는 것입니다. 이것을 할 수있는 방법이 있습니까?

+0

어, 내 cancan 사용을 감사해야 할 것입니다. 호기심에서 벗어나 개발자 및 프로덕션 환경에서 모두 그렇게합니까? – miked

+0

당신의 협회에서 한 줄로 모든 일이 일어나고 있다는 사실을 나는 쉽게 알 수 없습니다. 그러나 아마도 사용자의 모든 역할을'User.includes (: roles) .find (@ user.id)'와 같이로드 할 수있을 것입니다. 그런 다음 하나의 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" } 

역할이 단일 쿼리에서 메모리로 읽혀지면 30 개의 쿼리가 없습니다.

+0

가변 캐싱. 확실히. 그냥 cancan .. – pduersteler

관련 문제