忍者ブログ
ブログツール、2007/11/06作成
[59] [58] [57] [56] [55] [54] [53] [52] [51] [50] [49
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

普通にモデルを作っていて、一意性を確保したい属性には、validates_uniqueness_ofでチェックするのがRails流。
スマートにかけていいよね~とか思っていると、ここに落とし穴が。

まず、MySQLをRDBMSに利用している場合のみらしいが、
オプションの :case_sencitive が効かない

大文字小文字を認識してくれないのであるよ。
同じ理由で、ActiveRecord.countもActiveRecord.findも正しくない結果が帰ってくる。

で、ActiveRecord.find/countの時は、:conditionsオプションを指定するときに、
BINARY句を追加する。

こんな感じ
Hoge.find(:conditions=>["BINARY name = ?", "hoge"])

まあ、これはいいとして、validates_uniqueness_ofではどうするか、ということになる。
手っ取り早いが根本的でない解決法は、validates_uniqueness_ofを使わない、という選択肢。
代わりにvalidateメソッドを定義して、
そこでcountを発行して存在するかをチェックする。

このとき、自身がnew_record?かどうかで、自分を除外するコードを足すかどうかを判別する必要がある。

根本的な解決は、ActiveRecord/validate.rbのvalidates_uniqueness_ofをオーバーライドする事になる。
属性の型を認識して、BINARY句を追加するか判別しないといけない。

しかし、更に問題なのはvalidate_uniquness_ofではレコードの一意性が保証されないこと。
いわゆる、トランザクションとかロックの問題なんだけど、これはDBMSに丸投げするのが正解。

マイグレーションを使っているなら最後にユニークインデックスを張ってやる

add_index :tabel_name, :colun_name, :unique=>true

これは、validates_uniqueness_ofを使っている以上はどの場合もそうらしい。

やれやれ。
PR
この記事にコメントする
name
title
color
mail
URL
comment
pass   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
secret (チェックを入れると管理人だけに表示できます)
この記事へのトラックバック
この記事にトラックバックする:
ついめ~じ
ブログ内検索
フリーエリア
サニーカメラ
Powered by Ninja Blog    template by Temp* factory    icon by MiniaureType

忍者ブログ [PR]