1. ホーム
  2. ruby-on-rails

[解決済み] Rails の "validates_uniqueness_of" の大文字小文字を区別する機能

2022-11-26 02:34:13

質問

SQLLite3を使用したモデルです。

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

例えば、"Yale"を追加した後、"Yale"を追加することはできませんが、次のようになります。 を追加することができます。 は追加できますが、は追加できます。

編集:それを見つけた - 。 アクティブレコードの検証

どのように解決するのですか?

validates_uniqueness_of :name, :case_sensitive => false はトリックを実行しますが、次のことに注意する必要があります。 validates_uniqueness_of ではなく は、複数のサーバ/サーバプロセス(例:Phusion Passengerの実行、複数のMongrelなど)またはマルチスレッドサーバがある場合、一意性を保証するものではありません。 それは、このような一連のイベントが発生する可能性があるからです(順番は重要です)。

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

の "同時実行と整合性" も参照してください。 validates_uniqueness_of Railsのドキュメントを参照してください。

から Ruby on Rails 第3版 :

<ブロッククオート

...その名前にもかかわらず、validates_uniqueness_ofはカラムの値が一意であることを実際に保証するものではありません。できることは、検証が行われた時点で、検証対象のレコードと同じ値を持つカラムがないことを確認することだけです。一意であるべきカラムに同じ値を持つレコードを同時に2つ作成し、両方のレコードが検証をパスすることもあり得ます。一意性を強制する最も信頼できる方法は、データベースレベルの制約を用いることです。

以下も参照してください。 このプログラマの経験 validates_uniqueness_of .

これがよく起こる方法の1つは、新しいアカウントを作成するときに、誤ってWebページから二重投稿してしまうことです。 これは、ユーザーが受け取るのは 2 番目の (醜い) エラーであり、実際には登録に成功したのに、登録に失敗したと思わせてしまうため、解決するのが難しい問題です。 これを防ぐために私が見つけた最良の方法は、二重投稿を防ぐためにjavascriptを使用することだけです。