У меня есть модель Invitation
, которая представляет приглашение присоединиться к подписке. В любой момент времени должно быть только Invitation
с определенной комбинацией email
/subscription_id
, если в других записях с соответствующими email
/subscription_id
также есть state
из 'declined'
.Как я могу validate_uniqueness_of, если областью действия для двух атрибутов, только если один атрибут для сопоставления существующих записей не равен определенному значению?
я могу в настоящее время проверки на уникальность, учитывая, что электронная почта и subscription_id комбинация уникальна:
Моя Invitation
модель:
validates :email, :uniqueness => { :scope => :subscription_id }
Rspec (проходит):
it { should validate_uniqueness_of(:email).scoped_to(:subscription_id) }
Однако я хочу пропустить проверку уникальности, если сопоставимые модели (базы) в базе данных имеют state
, что равно 'declined'
.
Если состояние существующей модели «отклонено», проверка должна пройти.
Первое, что приходит на ум:
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')
Update:
я сделал это и работало:
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
Действительно близко к тому, что я должен работать так, как вы разместили это. Я уверен, что ваше решение сработало бы так же хорошо, как очень похоже на решение, которое я придумал. – Ecnalyr