Respostas:
add_index :people, [:firstname, :lastname, :dob], :unique => true
De acordo com howmanyofme.com, "Existem 46.427 pessoas nomeadas John Smith" somente nos Estados Unidos. Isso é cerca de 127 anos de dias. Como isso está bem acima da vida útil média de um ser humano, isso significa que um conflito de DOB é matematicamente certo.
Tudo o que estou dizendo é que essa combinação específica de campos exclusivos pode levar a extrema frustração de usuário / cliente no futuro.
Considere algo realmente único, como um número de identificação nacional, se apropriado.
(Percebo que estou muito atrasado para a festa com este, mas pode ajudar futuros leitores.)
Você pode adicionar uma restrição sem um índice. Isso dependerá do banco de dados que você estiver usando. Abaixo está um código de migração de amostra para o Postgres. (tracking_number, carrier)
é uma lista das colunas que você deseja usar para a restrição.
class AddUniqeConstraintToShipments < ActiveRecord::Migration
def up
execute <<-SQL
alter table shipments
add constraint shipment_tracking_number unique (tracking_number, carrier);
SQL
end
def down
execute <<-SQL
alter table shipments
drop constraint if exists shipment_tracking_number;
SQL
end
end
Existem diferentes restrições que você pode adicionar. Leia os documentos
add_index
método. ;)
pg_constraint
tabela.
Olá Você pode adicionar um índice exclusivo em sua migração às colunas, por exemplo
add_index(:accounts, [:branch_id, :party_id], :unique => true)
ou separar índices exclusivos para cada coluna
No exemplo típico de uma tabela de junção entre usuários e postagens:
create_table :users
create_table :posts
create_table :ownerships do |t|
t.belongs_to :user, foreign_key: true, null: false
t.belongs_to :post, foreign_key: true, null: false
end
add_index :ownerships, [:user_id, :post_id], unique: true
Tentar criar dois registros semelhantes gerará um erro no banco de dados (Postgres no meu caso):
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_ownerships_on_user_id_and_post_id"
DETAIL: Key (user_id, post_id)=(1, 1) already exists.
: INSERT INTO "ownerships" ("user_id", "post_id") VALUES ($1, $2) RETURNING "id"
por exemplo, fazendo isso:
Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)
Exemplo totalmente executável: https://gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced
db/schema.rb
gerado: https://gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a
Por uma questão de integridade, e para evitar confusão, aqui estão três maneiras de fazer a mesma coisa:
Adicionando uma restrição exclusiva nomeada a uma combinação de colunas no Rails 5.2+
Digamos que temos a tabela Locais que pertence a um anunciante e tem a coluna reference_code e você deseja apenas 1 código de referência por anunciante. então você deseja adicionar uma restrição exclusiva a uma combinação de colunas e nomeá-la.
Faz:
rails g migration AddUniquenessConstraintToLocations
E faça sua migração parecer algo como este liner:
class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
add_index :locations, [:reference_code, :advertiser_id], unique: true, name: 'uniq_reference_code_per_advertiser'
end
end
OU esta versão do bloco.
class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
change_table :locations do |t|
t.index ['reference_code', 'advertiser_id'], name: 'uniq_reference_code_per_advertiser', unique: true
end
end
end
OU esta versão SQL bruta
class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
execute <<-SQL
ALTER TABLE locations
ADD CONSTRAINT uniq_reference_code_per_advertiser UNIQUE (reference_code, advertiser_id);
SQL
end
end
Qualquer um destes terá o mesmo resultado, verifique seu schema.rb