2009-07-30 31 views
22

我已经升级到Rails 2.3.3(从2.1.x开始),我试图找出accepts_nested_attributes_for方法。我可以使用该方法更新现有的嵌套对象,但我不能用它来创建新的嵌套对象。由于人为的例子:如何使用accept_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 

如果我试图创建一个新的Product,与嵌套Note,如下:

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

它失败的消息验证:

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

我明白为什么会发生这种情况 - 这是因为Note课程上的validates_presence_of :product_id,因为在保存新记录时,Product对象没有id。但是,我不想删除此验证;我认为删除它是不正确的。

我也可以通过先手动创建Product,然后添加Note来解决问题,但是这样做会使accepts_nested_attributes_for的简单性失效。

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

回答

16

这是一个常见的循环依赖问题。有一个existing LightHouse ticket值得一试。

我期望在Rails 3中这会得到很大的改善,但是在此期间你必须做一个解决方法。一种解决方案是设置一个虚拟属性,它在嵌套时设置以使验证有条件。

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

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

<%= note_form.hidden_field :nested %> 

这应该是足够有nested属性通过嵌套形式创建记事时设置。 未经测试。

+11

在Rails 3这个问题通过加入解决。见例如http://www.daokaous.com/rails3.0.0_doc/classes/ActiveRecord/Associations/ClassMethods.html#M001988“双向关联”部分下 – 2010-06-09 12:47:10

+2

我选择禁用验证时:id == nil 。因为只有在编写新的嵌套记录时才会发生这种情况,所以我希望这会很安全。奇怪的是,这个问题一直到2.3.8。 – aceofspades 2010-09-27 16:48:13

3

瑞安的解决方案实际上是真的很酷。 我去了,让我的控制器变胖了,所以这个嵌套不会出现在视图中。主要是因为我的观点有时候是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 
相关问题