Ты можешь использовать validates
для проверки uniqueness
по одному столбцу:
validates :user_id, uniqueness: {scope: :friend_id}
Синтаксис проверки для нескольких столбцов аналогичен, но вместо этого вы должны предоставить массив полей:
validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}
Однако приведенные выше подходы к проверке имеют условие состязания и не могут обеспечить согласованность. Рассмотрим следующий пример:
Записи таблицы базы данных должны быть уникальными n полям;
несколько ( два или более ) одновременных запросов, обрабатываемых отдельными процессами каждый ( серверы приложений, фоновые рабочие серверы или что вы используете ), обращайтесь к базе данных, чтобы вставить одну и ту же запись в таблицу;
каждый процесс параллельно проверяет, есть ли запись с тем же n полями;
проверка для каждого запроса проходит успешно, и каждый процесс создает запись в таблице с теми же данными.
Чтобы избежать такого поведения, нужно добавить уникальное ограничение в таблицу БД. Вы можете установить его с помощью add_index
помощника для одного (или нескольких) полей, выполнив следующую миграцию:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :table_name, [:field1, ... , :fieldn], unique: true
end
end
Предупреждение : даже после того, как вы установили уникальное ограничение, два или более одновременных запроса будут пытаться записать одни и те же данные в базу данных, но вместо создания дублированных записей это вызовет ActiveRecord::RecordNotUnique
исключение, которое вы должны обработать отдельно:
begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end