1

ユーザーの電子メール アドレスの大文字と小文字を区別しない一意性を必要とする移行で使用する適切な検証を見つけようとしています。要するに、validate :email, :uniqueness => {:case_sensitive => false}Rails や ActiveRecord を使用するためにすべてを変換する必要がないようなものが欲しいのです。正規表現を介して電子メールを実行できましたが、その解決策は好きではありません。

使用できるというコメント[1]を見つけましたが、
validates_unique(:email){ |ds| ds.opts[:where].args.map! { |x| Sequel.function(:lower, x)}; ds}
そのコードが何をしているのか理解できず、そのdsオブジェクトが何であるか、または何が起こっているのかわからない場合は、そのコードを使用したくありません (なぜmap!、 postgresql にはSequel.functionof があり:lowerますか? ... おそらくですが、私にはわかりません。)

[1] http://comments.gmane.org/gmane.comp.lang.ruby.sequel/6447


だから私は2つのことのうちの1つに答える必要がありSequel.migrationます.
- または -
2) オンラインで見つけたそのコード スニペットが実際に欲しいものである場合、それは何をし、どのように機能しますか? (dsオブジェクトとは何ですか? この検証はデータベースに対して何を行いますか?)

4

1 に答える 1

6

Tin Man が述べたように、検証と制約を混同しています。制約を追加して について話そうとしていますがSequel.migration、それらは検証とは何の関係もありません。

データベースの制約を追加する場合は、移行で次のようにする必要があります。

alter_table(:table){add_unique_constraint Sequel.function(:lower, :email)}

これは、データベースが大文字と小文字を区別しない方法で電子メールの重複を許可しないようにするためです。

検証は、適切なエラー メッセージをユーザーに表示するためのものです。それらは保存する前に実行されるため、データベースが例外を発生させる代わりに (対処が困難です)、適切なエラー メッセージが表示されます。

そのコメントが言及しているように、ハックなしでは、大文字と小文字を区別するデータベースで大文字と小文字を区別しないルックアップに validates_unique を使用することはできません。validates_unique が追加のオプションを受け入れる必要があります (将来追加される可能性があります)。

そのようなハックを使用したくない場合は、検証を手動で行う必要があります。

dataset = model.where{|o| {o.lower(:email)=>o.lower(email)}}
dataset.exclude(pk_hash) unless new?
errors.add(:email, 'is already taken') unless ds.count == 0

そのハックが何をするかという点では、 一意性をチェックするために使用するdsインスタンスSequel::Datasetです。validates_uniqueとするとvalidates_unique :email、次のようになります。

model.where(:email=>email)
# WHERE email = 'some email'

ds.opts[:where]そのデータセットから where 句を抽出し、次のlowerように where 句を変換するために、引数を変換して SQL 関数呼び出しにラップします。

model.where{|o| {o.lower(:email)=>o.lower(email)}}
# WHERE lower(email) = lower('some email')

モデルのデータセットがまだフィルタリングされていない場合にのみ機能するため、これはハックです。

于 2012-07-12T14:57:49.383 に答える