Trilhos: validar a exclusividade de duas colunas (juntas)

Respostas:

230

Você pode usar uma validação de exclusividade com a scopeopção

Além disso, você deve adicionar um índice exclusivo ao banco de dados para impedir que novos registros passem nas validações quando verificados ao mesmo tempo antes de serem gravados:

class AddUniqueIndexToReleases < ActiveRecord::Migration
  def change
    add_index :releases, [:country, :medium], unique: true
  end
end



class Release < ActiveRecord::Base
  validates :country, uniqueness: { scope: :medium }
end
tompave
fonte
+1 para o índice, mas -1 para o uniqueque não é reconhecido. Para essa parte, usei a resposta abaixo.
Aleks
7
Sim, desculpe, a chave de validação deve ser uniqueness, não unique. Consulte a documentação vinculada. Corrigindo a resposta.
tompave
1
Hum, legal, obrigado :) Repetir - colocar o índice eleva a solução para o próximo nível, e não apenas as outras soluções de "codificação" em que estive executando, antes de encontrar esta resposta. +1 para isso #
Aleks
70

Todas as respostas acima estão faltando como validar a exclusividade de vários atributos em um modelo. O código abaixo pretende dizer como usar vários atributos em um escopo.

validates :country, uniqueness: { scope: [:medium, :another_medium] }

Valida a exclusividade de countrytodas as linhas com valores de mediume another_medium.

Nota: Não se esqueça de adicionar um índice na coluna acima, isso garante recuperação rápida e adiciona uma validação no nível do banco de dados para registros exclusivos.

Atualização: Para adicionar um índice ao criar tabela

t.index [:medium, :another_medium], unique: true
Aamir
fonte
41

Você pode passar um :scopeparâmetro para o seu validador como este:

validates_uniqueness_of :medium, scope: :country

Veja a documentação para mais alguns exemplos.

KM Rakibul Islam
fonte
8
@DennisBest Ele "funciona", mas não protege contra as condições da corrida. Se dois clientes fizerem pedidos simultâneos, ambos poderão passar na validação se nenhum deles for confirmado no banco de dados antes que o outro seja validado. Você também precisa de uma restrição exclusiva do banco de dados, como na resposta do tompave.
soupdog