Rails:2つの列の一意性を検証(一緒に)


回答:


230

オプションで一意性検証を使用できscopeます。

また、新しいレコードが書き込まれる前に同時にチェックされたときに検証に合格しないようにするには、DBに一意のインデックスを追加する必要があります。

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

インデックスの場合は+1、unique認識されない場合は-1 。その部分について、私は以下の答えを使用しました。
Aleks

7
はい、申し訳ありませんが、検証キーはでuniquenessはなくである必要がありuniqueます。リンクされたドキュメントを参照してください。答えを修正します。
16年

1
うーん、いいですね、ありがとう:)繰り返しますが、この答えを見つける前に、インデックスを付けると、ソリューションを次のレベルに引き上げることができます。そのための+1
アレクス

70

上記のすべての回答には、モデル内の複数の属性の一意性を検証する方法がありません。以下のコードは、スコープで複数の属性を使用する方法を伝えることを目的としています。

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

それはの一意性を検証countryする値を持つすべての行にmediumanother_medium

注:上記の列にインデックスを追加することを忘れないでください。これにより、高速な検索が保証され、一意のレコードに対するDBレベルの検証が追加されます。

更新:テーブルの作成中にインデックスを追加するため

t.index [:medium, :another_medium], unique: true

41

次の:scopeようにパラメーターをバリデーターに渡すことができます:

validates_uniqueness_of :medium, scope: :country

その他の例については、ドキュメントを参照してください。


8
@DennisBestこれは「機能します」が、競合状態から保護されません。2つのクライアントが同時に要求を行う場合、どちらもデータベースにコミットされてから、もう一方が検証される前に、両方が検証に合格する可能性があります。tompaveの答えのように、データベースの一意の制約も必要です。
soupdog
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.