2011-08-09 2 views
14

나는 active 열이있는 모델을 가지고 있습니다.이 모델은 부울입니다. 이 false으로 설정되어 있으면 company_id에 대해 새로 추가 된 모든 레코드의 고유성을 확인하여 원하는만큼 많은 레코드를 추가 할 수 있습니다. 각 company_id에 대해 하나의 active 레코드 만 있어야합니다.Rails 3은 열에 대해 하나의 값의 고유성을 확인합니까?

어떻게 작성하나요? 나는 이미 시도했다 :

validates :company_id, :uniqueness => { :scope => :active } 

하지만 그 또한 관계없이, 나는 같은 active 상태 테이블에 두 개 이상의 company_id 년대를 가질 수 없어 false (있도록되는 active의 독특한 조합에 대한 유효성을 검사하는 것 무엇 active입니다) - 위의 유효성 검사는 company_id에 대해 두 개의 레코드를 허용합니다. 하나는 active = false이고 다른 하나는 active = true입니다. 이 두 레코드가 들어 오면 검증은 다른 모든 것을 차단합니다.

scope :active, where(:active => true) 

을하지만 그 (위와 같이 동일한 문제가) 전혀 검증을 변경하지 않는 것 :

나는 다음이를 추가했습니다.

내가 너무 오래 active이 거짓 같은 company_id에 많은 레코드를 추가, 만 company_id 당 하나의 active = true을 허용 할 수 있도록이 검증을 쓸 수 있습니까?

답변

13

동일한 블록을 통해 여러 속성을 전달하려는 경우에만 validates_each을 사용할 필요가 없습니다. 맞춤 인증을 만드십시오.

validate :company_id_when_active 

def company_id_when_active 
    if active? and CompanyTerm.exists? ["company_id = ? AND active = 1 AND id != ?", company_id, id.to_i] 
    errors.add(:company_id, 'already has an active term') 
    end 
end 
-2
validates :company_id, :uniqueness => { :scope => :active } unless Proc.new { self.active } 

이 어쩌면 당신은 당신의 솔루션을 기반으로 대답에 따라 기업 자체

validates :company, :uniqueness => { :scope => :active } unless Proc.new { self.active } 

편집

전화를 좀 더 효율적으로 원하는 :

scope :active, where(:active => true) 

validates_each :company do |model, attr, value| 
    model.errors.add(attr, 'already has an active term') if CompanyTerm.active.exists?(:company_id => value) 
end 
+0

이 다음 여부를 확인하는, 내가 TRUE ''로 설정 active''와 빈 테이블에 새로운 레코드를 추가하려고하는 내 첫 번째 테스트 케이스의 패스를하지 않습니다 'active'가'true'로 설정된 또 다른 새로운 레코드는 유효하지 않거나 (같은'company_id'를 가진) 유효하지 않습니다. 사실, Proc가 호출되지 않는 것 같습니다. – neezer

+0

이 _answer_은 여러 가지 방법으로 구분되어 있습니다. – smathy

4

좋아, 나는 마침내 이것을 알아 냈다고 생각합니다. 레일 가이드 위로 확인

이 솔루션에 저를지도 한, validates_each를 알려준 :

scope :active, where(:active => true) 

validates_each :company do |model, attr, value| 
    active = CompanyTerm.active.where(:company_id => value) 
    model.errors.add(attr, 'already has an active term') unless active.empty? 
end 

즉이 쓸 수있는 가장 효율적인 방법인지 잘 모르겠지만, 그것을 작동합니다. 나는 모든 제안에 열려 있습니다!

1

이전 주제이지만 가장 간단한 해결책이 있습니다. 위의 대답은 거의 정확합니다. 이것에 대한 더 나은 솔루션을 제공 4+

validates :active, :uniqueness => { :scope => :company_id }, :if => :active 
+0

하지만 여전히 update_all (: active => false)를 사용하여 모두 'true'로 할당 할 수 있습니다. – jdscosta91

+3

잘못된 것입니다 - 다른 모델이 아닌 유효성 검사중인 모델에서 활성 값을 확인합니다 – koosa

+0

to @koosa : 왜 이것이 잘못된지 말해 주시겠습니까? 유효성 검사 모델이 비활성 상태 (활성 = false)이면 회사 범위 내에서 활성 상태의 유니티를 검증하지 않는 것이 좋습니다 –

6

레일 : 당신은 같은 키로 :if 문을 사용할 수 있습니다.

validates_uniqueness_of :company_id, conditions: -> { where(active: true) } 

체크 아웃 documentation

관련 문제