Odpowiedzi:
add_index :people, [:firstname, :lastname, :dob], :unique => true
Według howmanyofme.com w samych Stanach Zjednoczonych 46.427 osób nazywa się John Smith. To około 127 lat dni. Ponieważ jest to znacznie więcej niż średnia długość życia człowieka, oznacza to, że zderzenie DOB jest matematycznie pewne.
Mówię tylko, że ta szczególna kombinacja unikalnych pól może w przyszłości doprowadzić do skrajnej frustracji użytkownika / klienta.
W razie potrzeby weź pod uwagę coś, co jest rzeczywiście unikalne, na przykład krajowy numer identyfikacyjny.
(Zdaję sobie sprawę, że jestem bardzo spóźniony na przyjęcie z tym, ale może to pomóc przyszłym czytelnikom.)
Możesz chcieć dodać ograniczenie bez indeksu. Zależy to od używanej bazy danych. Poniżej znajduje się przykładowy kod migracji dla Postgres. (tracking_number, carrier)
to lista kolumn, których chcesz użyć dla ograniczenia.
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
Możesz dodać różne ograniczenia. Przeczytaj dokumentację
add_index
metody. ;)
pg_constraint
tabeli.
Cześć Możesz na przykład dodać unikalny indeks w migracji do kolumn
add_index(:accounts, [:branch_id, :party_id], :unique => true)
lub oddzielne unikalne indeksy dla każdej kolumny
W typowym przykładzie tabeli łączenia między użytkownikami i postami:
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
Próba utworzenia dwóch podobnych rekordów spowoduje błąd bazy danych (w moim przypadku Postgres):
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"
np. robiąc to:
Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)
W pełni działający przykład: https://gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced
db/schema.rb
wygenerowane: https://gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a
Ze względu na kompletność i dla uniknięcia nieporozumień, są trzy sposoby zrobienia tego samego:
Dodanie nazwanego, unikalnego ograniczenia do kombinacji kolumn w Railsach 5.2+
Załóżmy, że mamy tabelę Lokalizacje, która należy do reklamodawcy i zawiera kolumnę kod_referencyjny, a Ty chcesz mieć tylko jeden kod referencyjny na reklamodawcę. więc chcesz dodać unikatowe ograniczenie do kombinacji kolumn i nazwać je.
Robić:
rails g migration AddUniquenessConstraintToLocations
I spraw, aby Twoja migracja wyglądała jak ta jedna linijka:
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
LUB ta wersja bloku.
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
LUB ta surowa wersja SQL
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
Każde z nich będzie miało ten sam wynik, sprawdź schema.rb