Вы можете использовать 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