Você pode usar validates
para validar uniqueness
em uma coluna:
validates :user_id, uniqueness: {scope: :friend_id}
A sintaxe para a validação em várias colunas é semelhante, mas você deve fornecer uma matriz de campos:
validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}
No entanto , as abordagens de validação mostradas acima têm uma condição de corrida e não podem garantir consistência. Considere o seguinte exemplo:
os registros da tabela de banco de dados devem ser únicos por n campos;
várias ( duas ou mais ) solicitações simultâneas, tratadas por processos separados cada ( servidores de aplicativos, servidores de trabalho em segundo plano ou o que você estiver usando ), acessam o banco de dados para inserir o mesmo registro na tabela;
cada processo em paralelo valida se há um registro com os mesmos n campos;
a validação para cada solicitação é aprovada com êxito e cada processo cria um registro na tabela com os mesmos dados.
Para evitar esse tipo de comportamento, deve-se adicionar uma restrição exclusiva à tabela db. Você pode configurá-lo com o add_index
auxiliar para um (ou vários) campos executando a seguinte migração:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :table_name, [:field1, ... , :fieldn], unique: true
end
end
Advertência : mesmo depois de definir uma restrição exclusiva, duas ou mais solicitações simultâneas tentarão gravar os mesmos dados no banco de dados, mas, em vez de criar registros duplicados, isso criará uma ActiveRecord::RecordNotUnique
exceção, que você deve tratar separadamente:
begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end