ネストしたアトリビュートのバリデーションを自分のレールアプリで実行するには、何時間も苦労しています。小さな注意点は、親の属性に基づいてネストされた属性を動的に検証しなければならないことです。Railsはトランザクショナルオブジェクトのaccepts_nested_attributes_forを受け入れます。
私の設定は次のとおりです。私は多くの異なる関連モデルを持つ親があり、親を保存するたびにそれらのネストされた属性を検証したいと考えています。私が保存したいとき、私は親にupdate_attributesを呼んで私のコントローラで
class Parent < ActiveRecord::Base
attr_accessible :children_attributes, :status
has_many :children
accepts_nested_attributes_for :children
validate :validate_nested_attributes
def validate_nested_attributes
children.each do |child|
child.descriptions.each do |description|
errors.add(:base, "Child description value cant be blank") if description.value.blank? && parent.status == 'validate_children'
end
end
end
end
class Child < ActiveRecord::Base
attr_accessible :descriptions_attributes, :status
has_many :descriptions
belongs_to :parent
accepts_nested_attributes_for :descriptions
end
:検証が動的に変化しているという事実を考えると、私はモデルのカスタム検証メソッドを書かなければなりませんでした。今問題は、明らかに、レールはデータベースに対して検証を実行し、ユーザーまたはコントローラによって修正されたオブジェクトに対しては検証を実行しないということです。したがって、子供の価値はユーザーによって消去され、検証は合格しますが、データベースの項目が有効でないために後の検証は合格しません。
ここでは、このシナリオの簡単な例です:
parent = Parent.create({:status => 'validate_children', :children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#true
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => nil}}}})
#true!!/since child.value.blank? reads the database and returns false
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#false, same reason as above
検証は最初のレベルの団体のために働く、例えばChildが 'value'属性を持っていれば、私のように検証を実行できます。問題は、保存する前に確認することができない深い関連付けによるものです。
誰でもこれを解決する方法の正しい方向に私を指摘できますか?私が現在参照している唯一の方法は、レコードを保存し、それを検証し、検証が失敗した場合にそれらを削除/元に戻すことですが、正直言ってもっとクリーンなものを期待しています。
ありがとうございました!
SOLUTION
だから、それは私がカスタム検証で直接それらを参照することにより、深いネストされたモデルの検証を実行していたが判明し、この方法:
class Parent < ActiveRecord::Base
[...]
has_many :descriptions, :through => :children
[...]
def validate_nested_attributes
descriptions.each do |description|
[...]
end
end
end
何らかの理由で問題が生じます私は上記を持っていた。私のサンプルコードをテストし、それが動作していたことを報告してくれたSantoshに感謝します。これは、これを理解する正しい方向で私に指摘しました。
元の質問のコードは、この種の動的で深くネストされた検証のために機能します。
子供に次の検証で、この
ためvalidates_associatedを使うべきだと思います。それはタイプミスかもしれません。 1. '子供の価値は空白にすることはできません' - 一重引用符内の一重引用符。 2. && parent.status = 'validate_children' - これは比較ではありません。その割り当て –
オタクについて申し訳ありません!ここのコードは、私のアプリの単なる単純な例ですので、それは働いていない理由ではありませんが、それを指摘してくれてありがとう:) –