2013-08-22 4 views
0

구성원에 대해 하나의 테이블과 직원에 대해 두 테이블을 가지고 있는데 모두 id_number이라는 특성이 있으며이 특성은 필수가 아니며 null 일 수 있습니다.레일 교차 모델 유효성 검사

유효성 검사를 실행하여 id_number의 고유성을 보장 할 수 있으므로 직원에게 동일한 id_number이 구성원으로 추가되거나 그 반대의 경우 오류가 발생합니다.

나는 내 자신의 유효성 검증을 시도하지만 각 인스턴스에 대해 db를 치는 것은 일부 회사가 수십만 명의 직원을 한 번에 업로드하기 때문에 매우 느릴 것입니다.

답변

1

네 자신의 유효성 확인으로 가능합니다. 데이터베이스에 충돌해야한다고 생각합니다. 그렇지 않으면 이미 존재하는지 확인할 수 없습니다.

id_number에 색인을 추가하는 것이 좋습니다.

UPDATE는 : 상기 방법은 성능 향상을 위해 다음과 같이 변경 될 수있다 :

def your_validation 
    employee_ids = Employee.all.map(&:id_number) 
    if employee_ids.include?(self.id_number) 
    errors.add(:id_number, "is already taken") 
    else 
    member_ids = Member.all.map(&:id_number) 
    if member_ids.include?(self.id_number) 
     errors.add(:id_number, "is already taken") 
    end 
    end 
end 

첫번째 청소기이고, 두 번째는 더 빠를 것이다. 그러나 많은 db 항목과 벤치 마크 도구를 사용하여이를 확인하십시오.

+0

예 i 정찰을 추가하면 속도가 크게 빨라집니다. 그것은 내가 부딪히는 것과 비슷한 것처럼 보입니다. 단 한 가지는 당신이 하하 일을 할 것이라 확신합니다. 당신이 employee_ids.include의 순서를 바꿀 수 있을까요? – TheLegend

+0

? member_ids는 다음을 포함합니다. ... 이것은 직원 항목보다 훨씬 많은 구성원이있는 경우 속도를 향상시킬 수 있으며 그 반대의 경우도 마찬가지입니다. 첫 번째 ID_number가 이미 발견되면 다른 사례는 실행되지 않기 때문입니다. 나는 곧 나의 대답을 업데이트 할 것이다. – Mattherick

1

난 당신이 뭔가를 할 것입니다 생각 :

def your_validation 
    if self.id_number.present? 
    if Employee.exists?(:id_number=>self.id_number) || Member.exists(:id_number=>self.id_number) 
     errors.add(:id_number, "is already taken") 
    end 
    end 
end 

이 체크가 매우 빠르게 실행해야 ID_NUMBER 컬럼에 인덱스를 가지고 validates_uniqueness_of 단일 테이블에서 사용하는 것과 같은 검사의 경우. 모든 ID를 레일에 페치하는 것과 관련된 솔루션은 테이블이 커지면 문제가 발생하기 시작합니다.

또 다른주의해야 할 점은 응용 프로그램에서 여러 웹 서버 인스턴스를 한 번에 실행하는 경우 이러한 종류의 레일 측 검사는 스레드 간의 경합의 영향을 받기 때문에 고유성을 100 % 보장 할 수 없다는 것입니다. 이러한 상황에서 고유성을 보장하는 유일한 방법은 데이터베이스에 내장 된 기능을 사용하거나 데이터베이스 시퀀스와 같은 중복을 배제하는 소스에서 직접 id_numbers를 생성하는 것입니다.