如何使用accepts_nested_attributes_for创建嵌套对象

我已升级到Rails 2.3.3(从2.1.x开始),我正在尝试找出accepts_nested_attributes_for方法。 我可以使用该方法更新现有的嵌套对象,但我无法使用它来创建新的嵌套对象。 鉴于人为的例子:

 class Product < ActiveRecord::Base has_many :notes accepts_nested_attributes_for :notes end class Note < ActiveRecord::Base belongs_to :product validates_presence_of :product_id, :body end 

如果我尝试使用嵌套Note创建新Product ,如下所示:

 params = {:name => 'Test', :notes_attributes => {'0' => {'body' => 'Body'}}} p = Product.new(params) p.save! 

它使用以下消息validation失败:

 ActiveRecord::RecordInvalid: Validation failed: Notes product can't be blank 

我理解为什么会发生这种情况 – 这是因为Note类上的validates_presence_of :product_id ,并且因为在保存新记录时, Product对象没有id 。 但是,我不想删除此validation; 我认为删除它是不正确的。

我也可以通过首先手动创建Product ,然后添加Note来解决问题,但这会破坏accepts_nested_attributes_for的简单性。

是否有标准的Rails方法在新记录上创建嵌套对象?

这是一个常见的循环依赖问题。 现有的LightHouse门票值得一试。

我希望在Rails 3中有很大的改进,但与此同时你必须做一个解决方法。 一种解决方案是设置嵌套时设置的虚拟属性,以使validation成为条件。

 class Note < ActiveRecord::Base belongs_to :product validates_presence_of :product_id, :unless => :nested attr_accessor :nested end 

然后,您将此属性设置为表单中的隐藏字段。

 <%= note_form.hidden_field :nested %> 

这应该足以在通过嵌套表单创建注释时设置nested属性。 未经测试。

Ryan的解决方案实际上非常酷。 我去了,让我的控制器更胖,这样就不必在视图中出现这种嵌套了。 主要是因为我的观点有时是json,所以我希望能够在那里尽可能少地逃脱。

 class Product < ActiveRecord::Base has_many :notes accepts_nested_attributes_for :note end class Note < ActiveRecord::Base belongs_to :product validates_presence_of :product_id unless :nested attr_accessor :nested end class ProductController < ApplicationController def create if params[:product][:note_attributes] params[:product][:note_attributes].each { |attribute| attribute.merge!({:nested => true}) } end # all the regular create stuff here end end 

最好的解决方案是使用parental_control插件: http : //github.com/h-lame/parental_control