16

HABTM 관계가있는 두 개의 모델 (사용자 및 역할)이 있습니다.HABTM - 고유성 제약

  • 사용자 - has_and_belongs_to_many : - 다음 USER_ID와 ROLE_ID은 고유해야한다고 사용자
  • 내가 조인 (users_roles 테이블)에 고유성 제약 조건을 추가 할

belongs_to 역할

  • 역할을. 레일에, 우리는 일반적으로 HABTM 협회에 가입 관계를 대표하는 모델이없는, 물론

    validates_uniqueness_of :user, :scope => [:role] 
    

    : 레일에서 같을 것이다.

    제 질문은 제약 조건을 추가하는 가장 좋은 장소는 어디입니까?

  • 답변

    36

    당신은 테이블을

    add_index :users_roles, [ :user_id, :role_id ], :unique => true, :name => 'by_user_and_role' 
    

    보고 가입 고유성 추가 할 수 있습니다 (물론 이름과 설명이 열 값이다의) In a join table, what's the best workaround for Rails' absence of a composite key?

    당신이 다음 예외가 발생합니다 데이터베이스, 다루다.
    나는이 사건에 대한 레일 유효성 검사를 사용하기 위해 준비 모르겠지만,이 같은 자신의 유효성 검사를 추가 할 수 있습니다

    class User < ActiveRecord::Base 
    has_and_belongs_to_many :roles, :before_add => :validates_role 
    

    난 그냥 자동으로 데이터베이스 호출을 삭제하고 성공을보고 할 것입니다.

    def validates_role(role) 
        raise ActiveRecord::Rollback if self.roles.include? role 
    end 
    

    ActiveRecord :: Rollback은 내부적으로 캡처되었지만 다시로드되지 않습니다.

    편집

    내가 지정 유효성 검사을 추가 해요 부분을 사용하지 마십시오. 다소 효과가 있지만 더 좋은 대안이 있습니다. @Spyros으로 협회에

    사용 :uniq 옵션은 다른 답변에서 제안 :

    class Parts < ActiveRecord::Base 
        has_and_belongs_to_many :assemblies, :uniq => true, :read_only => true 
    end 
    

    (이 코드는 레일 가이드 3 절에서)입니다. Rails Guides v 3.2.13에서 읽기 4.4.2.19 찾기 : uniq

    Rails Guide v.4에서는 가능한 경쟁 조건으로 인해 고유성 검사에 대해 include?을 사용하는 것에 대해 경고합니다.

    조인 테이블에 인덱스를 추가하는 부분이 유지됩니다.

    +0

    감사합니다. 나는 HABTM 사용자와 그룹 (본질적으로 같은 종류의 역할 설정)을 위해 이것을 사용했다. – dennismonsewicz

    +1

    ': has_many'와는 달리 중복 제거가 habtm 연관에 대해 자동으로 처리되지 않는다는 점을 조금은 엿 봅니다. 편집 후 – prusswan

    +1

    이 게시되었습니다. 이 답변을 게시하고 잊어 버렸습니다. 그리고 나서 나는 관련된 문제를 발견했고 나는 사람들이 상향 투표를하는 대답을 가지고 있다는 것을 기억했고 나는 그것과 OMG를 점검했다! 나는 무엇을 생각하고 있었느냐! 내 대답을 사용했기 때문에 아무도 문제가 없기를 바랍니다. 나는 그것없이 충분히 나쁘다고 느낀다. 우리 모두에게 그것이 교훈입니다. 당신은 Stackoverflow에 서둘러 답답한 대답을두고 그것에 대해 잊어 버릴거야하지만 시간이 올 것이다 그것이 당신에게 튀어 나와 엉덩이에 물린거야. –

    5

    나는 uniq => true를 사용하면 중복 된 객체를 얻지 못할 것이라고 생각합니다. 하지만, db에 두 번째 파일을 작성하기 전에 중복 파일이 있는지 여부를 확인하려면 find_or_create_by_name_and_description (...)을 사용합니다.

    5

    내가

    class User < ActiveRecord::Base 
        has_and_belongs_to_many :roles, -> { uniq } 
    end 
    

    다른 옵션은 또한 대신 uniq

    distinct를 사용하는 것이 좋습니다 레일 (5)에서 here

    +0

    이런 식으로하면 잘못된 인수 번호를 얻을 수 있습니다. – inquisitive

    +0

    레일 4가 아니라 레일 3이 사용할 수 있습니다. –

    +0

    그러나이 유효성 검사는 모델 레벨에서만 가능합니다. 동시 요청을 처리하기 위해 DB 수준 검증이 필요합니다. – Tachyons

    4

    를 참조 선호 고유성

    has_and_belongs_to_many :foos, -> { distinct } do 
        def << (value) 
        super value rescue ActiveRecord::RecordNotUnique 
        end 
    end 
    
    을 보장하기위한이 시도
    +0

    작동하지만 아주 예뻐 보이지 않습니까? – Fritzz

    +1

    +1 자동 복구 용 고유 오류. 다른 속성을 저장하지 못하도록 복제 된 HABTM이 필요하지 않습니다. – TheRealMrCrowley