Rails accepts_nested_attributes_for дочерний не имеет родительского набора при проверке - PullRequest
10 голосов
/ 09 февраля 2010

Я пытаюсь получить доступ к своей родительской модели в моей дочерней модели при проверке. Я нашел кое-что об обратном свойстве в has_one, но мой Rails 2.3.5 не распознает его, поэтому он никогда не входил в релиз. Я не уверен, что это именно то, что мне нужно.

Я хочу проверить ребенка условно на основе родительских атрибутов. Моя родительская модель уже создана. Если дочерний элемент не был создан при обновлении родительского атрибута update_attributes, он не имеет доступа к родительскому элементу. Мне интересно, как я могу получить доступ к этому родителю. Это должно быть простым, что-то вроде parent.build_child устанавливает parent_id дочерней модели, почему он этого не делает при построении дочернего элемента для acceptpts_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 ]

12 голосов
/ 25 апреля 2013

У меня была в основном та же проблема с 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
8 голосов
/ 19 февраля 2011

У меня была похожая проблема: 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
7 голосов
/ 08 июля 2010

Вы не можете сделать это, потому что дочерний элемент в памяти не знает родителя, которому он назначен. Это знает только после сохранения. Например.

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

Если вы действительно считаете это необходимым.

P.S. Причина, по которой он этого не делает сейчас, заключается в том, что это не слишком просто. Необходимо четко указать, как получить доступ к родителю / ребенку в каждом конкретном случае. Комплексный подход с картой идентичности решил бы ее, но для более новой версии есть :inverse_of обходной путь. Некоторые обсуждения, такие как this имели место в группах новостей.

0 голосов
/ 07 июля 2010

проверьте эти сайты, может быть, они вам помогут ...

Ошибка проверки ассоциации вложенных атрибутов Rails

acceptpts_nested_attributes_ для проверки дочерней ассоциации не удалось

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

Похоже, rails назначит parent_id после успешной проверки потомков. (так как родитель имеет идентификатор после того, как он сохранен)

возможно стоит попробовать это:

child.parent.some_condition

вместо self.parent.some_condition ... кто знает ...

...