#ruby-on-rails #postgresql #ruby-on-rails-5
#ruby-on-rails #postgresql #ruby-on-rails-5
Вопрос:
У меня есть база данных, в которой электронная почта установлена как уникальная проверка со статусом. Я установил область видимости как значение int ‘status’, которое равно 1, когда активна конкретная учетная запись. Поэтому, если пользователь переключает свою страну, статус его учетной записи переключается на 0, и создается новая учетная запись с тем же адресом электронной почты, а статус устанавливается равным 1. Поэтому, чтобы решить эту проблему, я использовал составной уникальный ключ для «электронной почты» и «статуса» как,
validates :email, uniqueness: { scope: :status }
Итак, давайте проведем небольшой пробный запуск.
в настоящее время пользователь находится в стране X, и его адрес электронной почты abc@xyz.com
таким образом, база данных может выглядеть так
email: abc@xyz.com
status: 1
Теперь, если он переходит к
обновлениям базы данных country Y как,
[for company X]
email: abc@xyz.com
status: 0
[for company Y]
email:abc@xyz.com
status: 1
работает нормально
, но теперь, если наш путешественник отправится в страну Z,
база данных застрянет, как и сейчас, статус компании Y обновится до 0, и поскольку теперь эта комбинация не уникальна, поэтому вернет ошибку.
Также сложная задача здесь использовать только email и status в качестве ключей.
Чего я хочу добиться, так это того, что для определенного статуса электронной почты: 1 должно быть уникальным, а статус: 0 может быть любым количеством раз.
Итак, я пытался сформулировать оператор следующим образом
validates :email, uniqueness: { scope: :status }, if: :status == 1
но не повезло, так как я не могу принять значение статуса конкретного пользователя в модели.
Заранее спасибо!!
PS: Я новичок в ROR, поэтому предоставьте соответствующие ссылки, чтобы я мог узнать больше xD.
Ответ №1:
Возможно, вы захотите пересмотреть структуру своей базы данных.
Но одно из решений состоит в том, чтобы сделать:
validates_uniqueness_of :email, scope: :status, if: :active?
def active?
status == 1
end
Проверьте api для этой проверки здесь .
Но я настоятельно рекомендую вам переделать структуру базы данных, чтобы предотвратить это на уровне базы данных. Что-то вроде:
inactive_emails table
email | company
--------------------------------
one@exmaple.com | A
one@example.com | B
one@example.com | C
two@example.com | A
active_emails table
email | company
--------------------------------
one@example.com | D
two@example.com | E
Для модели неактивных электронных писем вы могли бы:
class InactiveEmails
validates_uniqueness_of :email, scope: :company
end
И для модели активных электронных писем:
class ActiveEmails
validates_uniqueness_of :emails, scope: :company
end
Таким образом, вы гарантируете, что у каждой компании есть уникальные активные электронные письма, и каждое электронное письмо может быть активным только для одной компании одновременно.
Теперь вам нужно переключать электронные письма между двумя таблицами. Вы могли бы использовать обратный вызов, например:
before_save :check_if_email_is_inactive_for_company
def check_if_email_is_inactive_for_company
if InactiveEmail.where(email: email, company: company).exists?
# remove from inactive? or inform user this email was deactivated before?
end
end
Страница Rails API — ваш друг.
Ответ №2:
Вы можете решить свою проблему многими способами, но я расскажу 2 способа
- Вы можете применить область действия следующим образом
validates :email, uniqueness: { scope: [:status,:country]}
- Если вы хотите обработать его с помощью области видимости для одного поля
validates :email, uniqueness: { scope: :status }, unless: lambda{ |user| user.status == 0 }
Если идентификатор пользователя равен x, приведенная выше проверка позволяет использовать идентификатор пользователя: x, статус: 0 несколько раз, но у вас может быть только одна комбинация user_id: x, статус 1.