Railsの「validates_uniqueness_of」の大文字と小文字の区別


93

ここにモデルがあります(私はSQLLite3を使用しています):

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

たとえば、「エール」を追加した後、「エール」を追加することはできませんが、「エール」追加することはできます。検証の大文字と小文字を区別しないようにするにはどうすればよいですか?

編集:見つけました- アクティブレコードの検証

回答:


232

validates_uniqueness_of :name, :case_sensitive => falseトリックはありませんが、あなたは心に留めておく必要があるvalidates_uniqueness_ofではないか、マルチスレッドサーバー(例えばのPhusion旅客、複数の雑種などを実行している)を使用すると、複数のサーバ/サーバ・プロセスを持っている場合は、一意性を保証します。これは、次の一連のイベントが発生する可能性があるためです(順序は重要です)。

  1. プロセスAは、「foo」という名前の新しいユーザーを作成するリクエストを受け取ります
  2. プロセスBは同じことを行います
  3. プロセスAは、「foo」の一意性を検証します。その名前がまだ存在していて、DBがその名前はまだ存在していないとDBに尋ねます。
  4. プロセスBは同じことを行い、同じ応答を受け取ります
  5. プロセスAがinsert新しいレコードのステートメントを送信し、成功する
  6. そのフィールドの一意性を必要とするデータベース制約がある場合、プロセスBはinsert新しいレコードのステートメントを送信し、SQLアダプターから返される醜いサーバー例外で失敗します。データベース制約がない場合、挿入は成功し、名前が「foo」の2つの行ができます。

validates_uniqueness_ofRailsのドキュメントの「同時実行性と整合性」も参照してください。

Railsの第3版のルビー

...その名前にもかかわらず、validates_uniqueness_ofは実際には列の値が一意であることを保証しません。それができることは、検証が実行されたときに検証されているレコードと同じ値を持つ列がないことを確認することだけです。2つのレコードが同時に作成され、一意である必要がある列に同じ値があり、両方のレコードが検証に合格する可能性があります。一意性を強制する最も信頼できる方法は、データベースレベルの制約を使用することです。」

参照してください。このプログラマの経験を持つがvalidates_uniqueness_of

これが一般的に発生する1つの方法は、新しいアカウントを作成するときにWebページから誤って二重に送信されることです。これは解決が難しい問題です。ユーザーが返すのは2番目の(醜い)エラーであり、実際には成功したにもかかわらず、登録が失敗したとユーザーに思わせるからです。これを防ぐ最善の方法は、javascriptを使用して二重送信を防ぐことです。


4
注意点として-ここで私はデシベルレベルの制約をutlizingすることにより、この問題を解決しようとするレールに提出してきたパッチです: rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/...
ヨルダンブラフ

また、「ユーザーが送信ボタンをダブルクリックした」という問題が多々ありますが、それは:disable_withを使用した修正の詳細です
Ghoti

76

Rails 3では、モデルでこれを行うことができます:

validates :name, :uniqueness => true

またはcase_sensitiveなし

validates :name, :uniqueness => {:case_sensitive => false}

これはまさに私が欲しいものです。
Jigar Bhatt

1
Railsを10年以上やっています。私はこのオプションについて単に学んでいるとは信じられません。Railsには、スキルレベルに関係なく、常に新しい知識がいくつかあります。
danielricecodes

24

大文字と小文字を区別しないオプションを指定できます

  validates_uniqueness_of :name, :case_sensitive => false

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.