DB에서 데이터 로드
묘사
헤이,CanCan이 내가 예상한 방식대로 행동하도록 하려고 허풍을 좀 떨었다.)Desive를 사용하여 인증하고 CanCan을 사용하여 인증하는 기본 설정은 다음과 같습니다.
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
has_many :my_model_permissions
has_many :my_models, :through => :my_model_permissions
end
class MyModel < ActiveRecord::Base
# normal relation to all users via their permissions
has_many :my_model_permissions
has_many :users, :through => :my_model_permissions
# special relation to owners, needed for CanCan!
has_many :my_model_owner_permissions, :class_name => "MyModelPermission", :conditions => "my_model_owner_permissions_my_models_join.variant = 'owner'"
has_many :owners, :through => :my_model_owner_permissions, :class_name => "User", :source => :user
end
class MyModelPermission < ActiveRecord::Base
belongs_to :user
belongs_to :my_model
validates_inclusion_of :variant, :in => %w{owner write read}
end
따라서 보시다시피 사용자는 일부 대상 (MyModel) 을 만들고 다른 사용자와 공유할 수 있습니다. (읽거나 읽거나 쓰기 권한을 얻을 수 있습니다.)지금 나는 다음과 같은 능력을 원한다.- 주인은 그들의 물건으로 뭐든 할 수 있어
- 객체의 제거를 제외한 모든 작업을 읽기 및 쓰기 권한이 있는 사용자가 수행할 수 있습니다.
- 읽기 권한이 있는 사용자만 해당 객체를 볼 수 있습니다.
- 소유자가 객체를 관리할 수 있는 권한
세 가지는 간단해 보였는데, 내가 이렇게 해결했다.
can :create, MyModel
can :manage, MyModel, :my_model_permissions => {:user_id => user.id, :variant => "owner"}
can :manage, MyModel, :my_model_permissions => {:user_id => user.id, :variant => "write"}
cannot :destroy, MyModel, :my_model_permissions => {:user_id => user.id, :variant => "write"}
can :read, MyModel, :my_model_permissions => {:user_id => user.id, :variant => "read"}
마지막 문제는 해결하기 어려울 것 같습니다. MyModel에 소유자 관계를 추가해야 합니다. 그렇지 않으면 테이블 연결이 문제를 해결할 수 없을 것 같습니다.소유자 관계(위 참조)를 추가한 후 다음과 같은 방법으로 해결했습니다. # only owner can manage permissions and invitations
can :manage, MyModelPermission, :my_model => {:owners => {:id => user.id}}
can :manage, MyModelInvitation, :my_model => {:owners => {:id => user.id}}
MyModelController의 설정은 다음과 같습니다.class MyModelsController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource :through => :current_user
[...]
end
현재 키나를 설정하는 것이 효과가 있지만 100%는 아닙니다.내가 전화한 모델이json all MyModels는 출력에 두 번 있습니다.여기 왜 이래?
나의 전체 설정에 문제가 있습니까?
콘솔에 따라 다음과 같은 SQL 명령이 실행됩니다.
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
MyModel Load (1.0ms) SELECT "my_models".* FROM "my_models" INNER JOIN "my_model_permissions" ON "my_models"."id" = "my_model_permissions"."my_model_id" WHERE "my_model_permissions"."user_id" = 2
Role Load (1.0ms) SELECT "roles".* FROM "roles" INNER JOIN "user_roles" ON "roles"."id" = "user_roles"."role_id" WHERE "user_roles"."user_id" = 2 AND "roles"."name" = 'Administrator' LIMIT 1
MyModel Load (1.0ms) SELECT "my_models".* FROM "my_models" INNER JOIN "my_model_permissions" "my_model_permissions_my_models" ON "my_model_permissions_my_models"."my_model_id" = "my_models"."id" INNER JOIN "my_model_permissions" ON "my_models"."id" = "my_model_permissions"."my_model_id" WHERE "my_model_permissions"."user_id" = 2 AND (("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'read') OR (("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'write') OR ("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'owner')))
도와 주셔서 감사합니다.토론 #1
@driehleMyModels Controller에서 색인 동작을 제공할 수 있습니까?이 네 개의 조회 중 마지막은 권한 검사를 하는 것 같다.마지막 질의에는 내부 조인 구문이 유효하지 않은 my model permissions my models 테이블이 포함되어 있습니다(내부 조인 "my model permissions""my model permissions my models").토론 #2
@mikepack 인덱스 작업은 특별한 점이 없습니다. 많거나 적거나 비어 있습니다.class MyModelsController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource :through => :current_user
def index
respond_to do |format|
format.html # index.html.erb
format.json { render json: @my_models.to_json().html_safe }
end
end
[... other CRUD actions ...]
end
또 다른 질문: MyModelPermission과 MyModelInvestment의:manage
는 추가:owner
관계가 필요 없는 상황에서 완성할 수 있습니까?토론 #셋
복제할 수 없습니다.몇 가지 초보적인 문제:- 어떤 버전의 CanCan입니까?
- 데이터베이스에 중복 레코드가 없으므로 (중복 레코드도 표시되지 않음) 확인
여러 MyModel 질의의 경우 컬렉션을 두 번 잡아도 두 결과가 결합되지 않습니다.line 160 of controller_resource.rb에서 알 수 있듯이 두 번째 호출에 할당된
@my_models
변수를 덮어씁니다.이것은 데이터베이스에 중복 기록이 존재하거나 JSON 서열화 기술이 중복 기록을 공개하거나 SQL이 중복 기록을 생성하거나 각종 다른 형식의 중복이 존재한다고 믿게 한다.물론 잘못된 SQL은 CanCan의 문제입니다.Also, is this really the query that gets generated and output or did you fiddle with it for the sake of the bug report? It appears to be invalid. `MyModel Load (1.0ms) SELECT "my_models".* FROM "my_models" INNER JOIN "my_model_permissions" "my_model_permissions_my_models" ON "my_model_permissions_my_models"."my_model_id" = "my_models"."id" INNER JOIN "my_model_permissions" ON "my_models"."id" = "my_model_permissions"."my_model_id" WHERE "my_model_permissions"."user_id" = 2 AND (("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'read') OR (("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'write') OR ("my_model_permissions"."user_id" = 2 AND "my_model_permissions"."variant" = 'owner')))`
토론 #4
@mikepack I can confirm this is indeed happening and I believe it's something to do with upgrading to rails 3.2.5. After upgrading from rails 3.2.3 to 3.2.5 it seems cancan is calling every can? :action, @instance
multiple times. Our view performance in views using can? is 5-6 times slower now.
토론 #5
It's not rails 3.2.5 it's something else, I am investigating right now.
토론 #6
I'm using rails 3.2.2 and cancan 1.6.7 if that helps...
토론 #7
Any updates on this?
토론 #8
I am seeing similar behavior on my app (Rails 2.3.12, cancan 1.6.8 and also tried with 1.6.7 with same results) which definitely stems from the same core problem: that oddly-named and unused inner join.
In my case, I have School, Student, and a join model SchoolStudent. A user should be allowed to view the complete school history for any student if that student is associated with the user's school:
can :read, SchoolStudent, :student => { :school_students => { :school_id => my_school_ids } }
따라서 student x에 있는 모든 학교를 보려면 다음과 같이 하십시오.student_x.school_students.accessible_by(current_ability)
나는 driehle처럼 중복된 항목을 얻을 것이다.나는 또 결과 중의 몇 줄을 빠뜨렸다. -(이 두 문제는 모두 질의가 정확하지 않은 데서 비롯된다.그것은 주어진 학생과 현재 학교의 기록만 되돌려주는 것이지 주어진 학생의 모든 기록이 아니다.이는 질의에서 명백히 알 수 있습니다.
SELECT `school_students`.* FROM `school_students`
INNER JOIN `students` ON `students`.id = `school_students`.student_id
INNER JOIN `school_students` school_students_students ON school_students_students.student_id = students.id
WHERE ((`school_students`.`student_id`=1161 AND `school_students`.`school_id` IN (3)))
조회를 정확하게 하려면 AND 뒤의 조건이 school_students_students
이 아니라 인용school_students
이 필요합니다.만약 내가 수동으로 조회를 수정한다면, 그것은 중복 줄 문제와 잃어버린 줄 문제를 복구할 것이다.토론 #9
@mikepack@driehle Bump.토론 #10
저는 이 문제를 연구하는 데 시간이 좀 걸렸습니다. 비록 간단한 답안이나 해결 방안이 없지만 흔히 볼 수 있는 오해를 발견했습니다. 즉, 끼워 넣는 조건에 사용되는Active Record API가 어떻게 작동해야 하는지입니다.Rails 3.2.6에 변화가 있는 것 같은데, 이전에는 부정확했던 멀티 해시가 현재 손상된 SQL을 만들었기 때문에 이 점을 강조하고 있다.다음은 몇 가지 유용한 단서로 해석하는 것이다
:student => { :school_students => { :school_id => my_school_ids } }
이제껏 진정으로 작용하지 말았어야 했다.http://coderwall.com/p/7u6-rg
https://github.com/rails/rails/issues/6718
토론 #11
친애하는 제출자, cancan/raynB가 6개월 동안 활동을 하지 않았고 다른 사람이 없으면 ryam 본인이 제출 허가를 받아서 cancan 프로젝트는 정체 상태에 있습니다.cancan은 rails 4에 대한 지원이 부족한 것을 포함하여 몇 가지 문제가 있습니다. cancan은 cancan을 향해 전진하고 있습니다.자세한 내용: #994
만약 당신의 부탁이 아직 적용되지 않는다고 생각한다면 당신은 매우 감사할 것이다.https://github.com/cancancommunity/cancancan)
우리는 다른 쪽에서 너를 만나기를 바란다.
Reference
이 문제에 관하여(DB에서 데이터 로드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://github.com/ryanb/cancan/issues/637텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)