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它现在不这样做的原因是因为它不太容易。需要明确告知如何在每种特定情况下访问父/子。使用身份映射的综合方法可以解决它,但对于较新的版本,有:inverse_of解决方法。像这样的一些讨论发生在新闻组上。

于 2010-07-08T02:46:29.270 回答
0

检查这些网站,也许他们会帮助你...

Rails嵌套属性关联验证失败

Accepts_nested_attributes_for 子关联验证失败

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

看来,rails 将在子验证成功后分配 parent_id。(因为父母在保存后有一个ID)

也许值得尝试:

child.parent.some_condition

而不是 self.parent.some_condition ...谁知道呢...

于 2010-07-07T09:26:12.080 回答