2

複合フォーム(aaa http://railsforum.com/viewtopic.php?id=28447)で複数の子モデルを使用しています。フォームはうまくいきますが、の子モデルのセットのプロパティを検証してから、フォームデータをデータベースに受け入れる必要があります。私は、これを行うための主に働く、非常にクルージングな方法を考え出した。よりよい方法が必要なように思われるので、私は提案を求めています...複数の子モデルを複合フォームで検証するレール

基本的に人はhas_manyディストリビューションです。ディストリビューションは(とりわけ)パーセンテージ属性を持っています。特定の人物については、その分布は有効であるために合計100%でなければならない。これは私に "トランザクション"を叫ぶが、私は最初にバリデーターにショットを与えるべきであると思った。

私はこれをカスタムバリデータとして書きましたが、バリデータは既にデータベースに保存されているデータに対してのみ動作します。フォームによって提出されたパラメータをチェックしませんでした。言い換えれば、保存されたフォームから無効なパーセンテージを入力することができました。その後、モデル内の不良データのために後続の編集がすべて失敗しました。

def update_attributes(params) 
    retval = true 
    self.transaction do 
    retval = super 

    unless distributions_exactly_100? 
     retval = false 
     errors.add_to_base("Distribution must add up to exactly 100%") 
     raise ActiveRecord::Rollback 
    end 
    end 
    retval 
end 

retvalのビジネスは醜いですが、これは多かれ少なかれ、時には作品(保留中のディストリビューションのいくつかは、ときにそれをフォームから欠落している:

次は私がトランザクションを追加し、私のPersonモデルでupdate_attributesを拡張しましたエラーを見つけて再レンダリングします)。私のdistirbutionsの関連付けが以下のようにヘルパーメソッドで定義されている場合は、update_attributes()(またはdistributions_exactly_100?)のヘルパーメソッドを使用することができません。割り当てられたばかりのコミットされていないディストリビューションのセットで動作するのではなく、

has_many :distributions do 
    def for_month_and_year(month, year) 
    find :all, :conditions => ['month = ? and year = ?', month, year] 
    end 

    def total_for_month_and_year(month, year) 
    sum :percentage, :conditions => ['month = ? and year = ?', month, year] 
    end 

    ... 

    def years_and_months 
    ds = find(:all, :order => 'year DESC, month DESC') 
    (ds.collect {|d| [d.year, d.month]}).uniq 
    end 

end 

私は考えることができる唯一の他の事はupdate_attributesへの途中で、テキストとして、自分自身をparamsは処理することです。しかし、それはちょうど間違っています。 :)

他の誰もが子供のコレクション全体で検証を行っていますか?それについて正しいことは何でしょうか?

答えて

2

update_attributesにエラーを設定することはお勧めしません。正当な場所で検証を行います。

問題を再確認すると、データベースで計算を実行するのではなく、メモリ内のディストリビューションで作業するように検証チェックを変更できますか?

# in Person model 
validate :ensure_distributions_equal_100 

def ensure_distributions_equal_100 
    percent = distributions.map(&:percent).sum 
    if percent != 100 
    errors.add_to_base("Distribution must add up to exactly 100%, they are #{percent}") 
    end 
end 
+0

はい、ありがとう、私はメモリ対DBの角度を計算したら、検証として呼び出される関数を書いています。 :) 妥当性検査が失敗したときに編集ビューを表示する方法にはまだ問題があります(一部の保留中の変更は失われていますが、すべてではありません)。 – korinthe

関連する問題