Каким образом я могу задать парную валидацию в rails на данные в таблице,чтобы они больше не повторялись,пример: user_id=1,friend_id=2,и эта строка с такими(парными)значениями больше в таблицу не заносилась?
Ответ
Для начала:
Любая валидация на уникальность должна сопровождаться unique constraint'ом в БД
В вашем случае, составным. Пример из документации (для миграции)
add_index(:accounts, [:branch_id, :party_id], unique: true)
Никаких исключений. Между проверкой на отсутствие дубликатов и непосредственной записью проходит немного времени, достаточно, чтобы две записи от разных процессов смогли пролезть в базу. Такая "ситуация, где параллельные процессы могут подраться между собой и что-то сломать" называется race condition.
Валидация уникальности комбинаций полей выполняется с помощью параметра :scope. Для разных форм валидации результат выглядит немножко по-разному (документация):
validates_uniqueness_of :user_name, scope: :account_id # двух полей
validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id] # трёх полей
validates :user_name, uniqueness: { scope: :account_id } # двух полей, sexy-синтаксис
Вообще говоря, unique constraint и unique index это не одно и то же, но эту задачу любой из них успешно выполнит.
В чём различие? Constraint "больше", он включает в себя аналогичный индекс. Те фичи БД, что требуют именно constraint, индексом не удовлетворятся. Но мы отвлеклись.
Лично я обжёгся этим с PostgreSQL, используя ON CONFLICT, который требует именно constraint, который не может быть частичным, т. е. покрывать лишь некоторые строчки таблицы. Обидный момент, потребовавший переделать пол-схемы.
Комментариев нет:
Отправить комментарий