Existe uma maneira de validar que um registro real é único e não apenas uma coluna? Por exemplo, um modelo / tabela de amizade não deve ter vários registros idênticos, como:
user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20
Existe uma maneira de validar que um registro real é único e não apenas uma coluna? Por exemplo, um modelo / tabela de amizade não deve ter vários registros idênticos, como:
user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20
Is there a rails-way way
. E você oferece a ele caminhos não-trilhos, mas padrão.The Active Record way claims that intelligence belongs in your models, not in the database.
validates :field_name, unique: true
é propenso a condições de corrida, portanto, mesmo contra trilhos, é preferível uma restrição real. @HarryJoy Vou votar uma resposta descrevendo a maneira de restrição.Respostas:
Você pode selecionar uma
validates_uniqueness_of
chamada da seguinte maneira.fonte
validates_uniqueness_of [:user_id, :friend_id]
. Talvez isso precise ser corrigido?Você pode usar
validates
para validaruniqueness
em uma coluna:A sintaxe para a validação em várias colunas é semelhante, mas você deve fornecer uma matriz de campos:
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: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:fonte
Isso pode ser feito com uma restrição de banco de dados nas duas colunas:
add_index :friendships, [:user_id, :friend_id], unique: true
Você pode usar um validador de trilhos, mas em geral eu recomendo o uso de uma restrição de banco de dados.
Mais informações: https://robots.thoughtbot.com/validation-database-constraint-or-both
fonte