Puede usar validates
para validar uniqueness
en una columna:
validates :user_id, uniqueness: {scope: :friend_id}
La sintaxis para la validación en varias columnas es similar, pero en su lugar debe proporcionar una matriz de campos:
validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}
Sin embargo , los enfoques de validación que se muestran arriba tienen una condición de carrera y no pueden garantizar la coherencia. Considere el siguiente ejemplo:
se supone que los registros de la tabla de la base de datos son únicos por n campos;
múltiples ( dos o más ) solicitudes concurrentes, manejadas por procesos separados cada una ( servidores de aplicaciones, servidores de trabajo en segundo plano o lo que sea que esté usando ), accedan a la base de datos para insertar el mismo registro en la tabla;
cada proceso en paralelo valida si hay un registro con los mismos n campos;
la validación para cada solicitud se pasa con éxito y cada proceso crea un registro en la tabla con los mismos datos.
Para evitar este tipo de comportamiento, se debe agregar una restricción única a la tabla db. Puede configurarlo con add_index
ayuda para uno (o varios) campo (s) ejecutando la siguiente migración:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :table_name, [:field1, ... , :fieldn], unique: true
end
end
Advertencia : incluso después de haber establecido una restricción única, dos o más solicitudes simultáneas intentarán escribir los mismos datos en db, pero en lugar de crear registros duplicados, esto generará una ActiveRecord::RecordNotUnique
excepción, que debe manejar por separado:
begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end