11

検証時に、子モデルの親モデルにアクセスしようとしています。has_oneで逆プロパティについて何かを見つけましたが、Rails 2.3.5はそれを認識しないため、リリースに組み込まれたことはないはずです。それがまさに私が必要としているものかどうかはわかりませんが。

親の属性に基づいて条件付きで子を検証したいと思います。私の親モデルはすでに作成されています。親のupdate_attributesで子が作成されていない場合、その子は親にアクセスできません。この親にアクセスするにはどうすればよいのでしょうか。parent.build_childのようなものが子モデルのparent_idを設定するのは簡単なはずですが、accepts_nested_attributes_forの子をビルドするときにそれを行わないのはなぜですか?

例えば:

class Parent < AR
  has_one :child
  accepts_nested_attributes_for :child
end
class Child < AR
  belongs_to :parent
  validates_presence_of :name, :if => :some_method

  def some_method
    return self.parent.some_condition   # => undefined method `some_condition' for nil:NilClass
  end
end

私のフォームは標準です:

<% form_for @parent do |f| %>
  <% f.fields_for :child do |c| %>
    <%= c.name %>
  <% end %>
<% end %>

更新方法あり

def update
  @parent = Parent.find(params[:id])
  @parent.update_attributes(params[:parent])   # => this is where my child validations take place
end
4

4 に答える 4

14

Rails 3.2でも基本的に同じ問題がありました。質問で示唆されているように、inverse_ofオプションを親の関連付けに追加すると、修正されました。

あなたの例に適用されます:

class Parent < AR
  has_one :child, inverse_of: :parent
  accepts_nested_attributes_for :child
end

class Child < AR
  belongs_to :parent, inverse_of: :child
  validates_presence_of :name, :if => :some_method

  def some_method
    return self.parent.some_condition   # => undefined method `some_condition' for nil:NilClass
  end
end
于 2013-04-25T12:22:18.663 に答える
8

同様の問題がありました:Ruby on Rails-ネストされた属性:子モデルから親モデルにアクセスするにはどうすればよいですか?

これが私が最終的にそれを解決した方法です。コールバックで親を設定する

class Parent < AR
  has_one :child, :before_add => :set_nest
  accepts_nested_attributes_for :child

private
  def set_nest(child)
    child.parent ||= self
  end
end
于 2011-02-19T06:43:45.227 に答える
7

メモリ内の子は割り当てられた親を知らないため、これを行うことはできません。保存後にのみ認識されます。例えば。

child = parent.build_child
parent.child # => child
child.parent # => nil

# BUT
child.parent = parent
child.parent # => parent
parent.child # => child

したがって、手動で逆アソシエーションを実行することで、この動作を強制することができます。例えば

def child_with_inverse_assignment=(child)
  child.parent = self
  self.child_without_inverse_assignment = child
end

def build_child_with_inverse_assignment(*args)
  build_child_without_inverse_assignment(*args)
  child.parent = self
  child
end

def create_child_with_inverse_assignment(*args)
  create_child_without_inverse_assignment(*args)
  child.parent = self
  child
end

alias_method_chain :"child=", :inverse_assignment
alias_method_chain :build_child, :inverse_assignment
alias_method_chain :create_child, :inverse_assignment

あなたが本当にそれが必要だと思うなら。

PSそれが今それをしていない理由は、それがあまりにも簡単ではないからです。それぞれの特定の場合に親/子にアクセスする方法を明示的に指示する必要があります。IDマップを使用した包括的なアプローチで解決できますが、新しいバージョンでは:inverse_of回避策があります。このようないくつかの議論はニュースグループで行われました。

于 2010-07-08T02:46:29.270 に答える
0

これらのサイトをチェックしてください、多分それらはあなたを助けるでしょう...

Railsのネストされた属性の関連付けの検証に失敗しました

accept_nested_attributes_for 子関連付けの検証に失敗しました

http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

子の検証が成功した後、レールはparent_idを割り当てるようです。(親は保存後にIDを持っているため)

これを試す価値があるかもしれません:

child.parent.some_condition

self.parent.some_condition の代わりに ... 誰が知っている...

于 2010-07-07T09:26:12.080 に答える