2009-06-08 6 views
4

最初の項目で、私はそれをデータベースに保存する前に(最後の6ヶ月で)それが一意であることを確認するためにフィールドを検証したい
は、どのように私はvalidates_uniqueness_of行います。フィールドを最後の6ヶ月の範囲

私はvalidates_uniqueness_of使用する必要があります考えています:フィールド、CASE_SENSITIVE => falseを、スコープ=> ...それは場合にのみ、ユニークである必要があります私のアプリケーションのために

、それは< 6ヶ月前に使用しました。

created_atと比較することを考えていますが、実際にどのように動くかわかりません。私は(私はこれらの余分なスペースがレールにしている場合、デフォルトで使用されていることを知っている私は何とか使用が誤って入れている可能性があることをテキストの前または後に任意のスペースを削除するために.strip使うべきだと思う

2番目の項目
彼らはそこに独特のファイルを作ることができます。)

誰かがこれが正しく行われるべきであるというヒントがあれば、本当に感謝します。

答えて

3

あなたは、おそらくこのような何かを行うことができます。

また
def validate 
    errors.add(:field, 'blah blah') if is_used_recently && !has_unique_field? 
end 

def has_unique_field? 
    Model.exists?(['field = ? and created_at > ?', self.field, 6.months.ago]) 
end 

def is_used_recently 
    self.created_at < 6.months.ago || self.new? # i don't know if created_at would be set by this point 
end 

あなたが渡すために新しい検証ハンドラを作成、または既存のものを拡張したい場合があります:それはあなたがしようとしている何かあればオプション内頻繁にやっている。

先頭と末尾の空白を取り除くには、「strip」が必要です。私は間違いを作ったなら、私に知らせて、私はこのことができます願ってい

before_validation :clean_up_whitespace 

def clean_up_whitespace 
    self.some_field.strip! # this does the strip in place 
end 

:あなたのような何かを行うことで、すべてのフィールドでこれを実行することができます!

+0

新しいレコードを作成するときにself.created_at <6.months.ago == trueと表示されるので、is_used_recentlyが指定フィールドで機能するとは思えませんが、6ヶ月以上作成された2番目のレコードを持つことができます前と同じ値で:フィールド –

+0

ああ、私は参照してください。私は間違った質問を読んで...私は私の答えを更新します。 – jonnii

+0

clean_up_whitespaceの情報をありがとう、 私は多くのフィールドでこれを使用していますので、私はsome_fieldをフィールドの配列にして、それらをループするだけで、私はself.variable_name私が自己を削除すると、variable_nameは何ですか。正面からは知っているが、現場には適用されない。私は単純なものを見逃していることを知っている。しかし、それを解決する方法がわからない:( – Datatec

10

validates_uniqueness_ofは、レコードが指定されたスコープ内の指定されたフィールドと同じ値で既に存在するかどうかをチェックすることによって機能します。 :scopeでは、一意性の範囲(明らかに)を定義できます。たとえば、ブログソフトウェアを作成していて、ブログごとに投稿タイトルを1回だけ使用したいのであれば、validates_uniqueness_of :title, :scope => :blog_idと書くことができます。範囲なしでは、システム全体で各タイトルを1回だけ使用できるようにします。 :scopeは、あなたが望むような複雑なチェックをさせません。

あなたはおそらく実行する必要がありますが(コードはモデル内なる)与えられた時間内で、問題のフィールドの一意性をチェックするために独自の検証機能を作成することです:

validate :field_must_be_unique_within_six_months 

def field_must_be_unique_within_six_months 
    return if field.blank? 
    num_duplicates = self.class.count(:conditions => ["field = ? AND created_at < ?", self.field, 6.months.ago]) 
    if num_duplicates > 0 
    errors.add(:field, :taken) 
    end 
end 

field_must_be_unique_within_six_months方法でしょうvalidates_uniqueness_ofと同様に動作します。同じフィールドが既に存在するレコードがある場合はエラーメッセージが追加されますが、日付もチェックされるという条件が追加されます。 validate :field_must_be_unique_within_six_monthsは、レコードの保存時に検証プロセスにメソッドを追加します。

DRYに違反することなく、同時に複数のフィールドを検証するには、次のような何かを行うにvalidates_eachを使用することができます。上記のブロックで

validates_each :field1, :field2 do |record, attr, value| 
    if record.class.exists?(["#{attr.to_s} = ? AND created_at < ?", value, 6.months.ago]) 
    errors.add(attr, :taken) 
    end 
end 

recordをレコードが検証され、attrは属性であります(だからfield1,field2など)、valueはその属性の値です。

+0

申し訳ありませんが、私はこれで本当に新しいです。このコードをモデルに置き、 というクラス名でラップしました。クラス名 Datatec

+0

フィールドがちょうど例として使用されたため、一意にしたい実際のフィールドが呼び出されます。 –

+0

OKですので、検証する各フィールドにこのコードを繰り返す必要がありますか?複数のフィールドでこれを行うためのDRYishメソッドはありますか? – Datatec