回答:
add_index :people, [:firstname, :lastname, :dob], :unique => true
howmanyofme.comによると、米国だけで「John Smithという名前の人は46,427人います」。それは約127年の日数です。これは人間の平均寿命を十分に超えているため、DOBの衝突が数学的に確実であることを意味します。
私が言っていることは、ユニークなフィールドの特定の組み合わせは、将来、ユーザー/顧客の極端なフラストレーションにつながる可能性があるということです。
必要に応じて、国民識別番号のように、実際にユニークなものを検討してください。
(私はこれでパーティーに非常に遅れていると思いますが、それは将来の読者の役に立つかもしれません。)
インデックスなしで制約を追加したい場合があります。これは、使用しているデータベースによって異なります。以下は、Postgresのサンプル移行コードです。 (tracking_number, carrier)
制約に使用する列のリストです。
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
追加できる制約はいくつかあります。 ドキュメントを読む
add_index
メソッドを使用する場合と同じになるとき、私見は生のSQLにドロップする必要はありません。;)
ユーザーと投稿の間の結合テーブルの典型的な例では:
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
2つの類似したレコードを作成しようとすると、データベースエラーがスローされます(私の場合は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"
例:
Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)
完全に実行可能な例:https : //gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced
db/schema.rb
生成:https : //gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a
完全を期すため、および混乱を避けるために、同じことを行う3つの方法を
次に示します。Rails 5.2以降の列の組み合わせに名前付き一意制約を追加する
広告主に属し、列reference_codeがあり、広告主ごとに1つの参照コードのみが必要なLocationsテーブルがあるとします。したがって、列の組み合わせに一意の制約を追加して名前を付けます。
行う:
rails g migration AddUniquenessConstraintToLocations
そして、移行を次のいずれかのように見せます。
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
または、このブロックバージョン。
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
または、この生の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
これらのどれでも同じ結果になります。 schema.rb