1

구독에 대한 가입 초대를 나타내는 Invitation 모델이 있습니다. email/subscription_id과 일치하는 다른 레코드의 state'declined' 인 경우를 제외하고 특정 email/subscription_id 조합을 사용하는 경우에만 Invitation을 하나씩 사용해야합니다.기존 레코드가 일치하는 속성 중 하나의 속성이 특정 값과 같지 않은 경우에만 두 속성의 범위를 지정할 때 validate_uniqueness_of를 어떻게합니까?

나는 현재 이메일 및 subscription_id 조합이 고유한지 주어진 고유성에 대한 유효성을 검사 할 수 있습니다 :

Invitation 모델 :

validates :email, :uniqueness => { :scope => :subscription_id } 

RSpec에 (통과) :

it { should validate_uniqueness_of(:email).scoped_to(:subscription_id) } 

그러나 고유성 검사를 건너 뛰고 싶습니다. 데이터베이스의 일치하는 모델 (들)은 'declined'과 동일한 state입니다.

기존 모델의 상태가 '거부 됨'인 경우 유효성 검사가 통과해야합니다.

validates :email, :uniqueness => { :scope => :subscription_id }, 
            :unless => lambda { |asset| asset.state == 'declined' } 

그러나 새로 만든 모델은, 내가 이전에 기존 레코드가있는 경우 확인하려면 '거절'의 상태가있는 경우는 확인하기 때문에 이것은 잘못된 것입니다 :

마음에 오는 첫번째 것은이다 'declined'의 상태

나는 또한이 시도 :

validates :email, :uniqueness => { :scope => :subscription_id, :message => 'subscriptionery do' }, 
            :if => lambda { |asset| asset.state == 'declined' } 

을하지만 내가 같은 이유로 가정 무엇을 실패합니다.

추가 범위를 검사하는 유효성 검사는 어떻게 작성합니까?


나는 다음과 같은 것을 쓰는 것 같은 느낌,하지만 그냥 내 생각을 설명하는 데 도움 구문 구성되어 있습니다 :

it { should validate_uniqueness_of(:email).scoped_to(:subscription_id) } 
            unless MyModel.where(:email == new_object.email, 
                 :subscription_id == new_object.subscription_id, 
                 :state == 'declined') 

업데이트 :

내가 한을 이것과 그것은 작동했습니다 :

validates :email, uniqueness: { scope: :subscription_id, message: 'The email address %{value} is already associated with this subscription.' }, if: :state_of_others_are_not_declined?, on: :create 

def state_of_others_are_not_declined? 
    Invitation.where(email: email).where(subscription_id: subscription_id).where.not(state: 'declined').any? 
end 

답변

1

어떻게하면 효과가 있습니까?

validate :unique_email_with_subscription_and_state 


def unique_email_with_subscription_and_state 
    errors.add(:email,"YOUR MESSAGE") if Invitation.where(email: self.email, subscription_id: self.subscription_id).where.not(state: 'declined').any? 
end 

이하여 email 일치, subscription_id 일치하고 state 거부되지 않은 모든 Invitiation의를 선택합니다. 발견되면 error:email에 추가합니다.이 같은 것

"SELECT invitations.* FROM invitatations WHERE email = '[email protected]' AND subscription_id = 2 AND state <> 'declined'" 

그 결과가 좋습니까?

+0

내가 게시 한 것과 똑같은 작업을 수행 할 수 있습니다. 당신의 솔루션은 내가 생각해 낸 솔루션과 매우 유사 할뿐만 아니라 효과가 있었을 것이라고 확신합니다. – Ecnalyr

관련 문제