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