我正在处理一个混乱的表单,其中包括管理具有两级嵌套的部分。它几乎可以工作,但是有一个障碍,我唯一能看到的与其他深层嵌套形式不同的是,有一个belongs_to关系而不是has_many。以下是模型:
Event
has_many :company_events, :dependent => :destroy
accepts_nested_attributes_for :company_events
CompanyEvent
belongs_to :company
accepts_nested_attributes_for :company, :update_only => true
belongs_to :event
belongs_to :event_type
Company
has_many :company_events
has_many :events, :through => :company_events
因此,通过链接表company_events,这是一个相当标准的多对多关系。有问题的表格是使用动态的“添加公司”Javascript按钮创建/编辑活动,所有这些都基于Ryan Bates的截屏视频和GitHub回购。
主要形式:
<table id="companies">
<tr><th>Company Name</th></tr>
<% f.fields_for :company_events do |builder| %>
<%= render 'company_event_fields', :f => builder, :f_o => nil %>
<% end -%>
</table>
<p><br/><%= link_to_add_fields "Add Company", f, :company_events, "events" %></p>
包含的表格如下。需要注意的一件重要事情是公司ID是通过Javascript更新设置的,我不会在这里包含,因为它很长。基本上,用户开始键入名称,显示自动完成列表,单击名称可在表单中设置公司名称和ID。
<tr class="company_event_fields">
<td>
<% f.fields_for(:company) do |company_form| -%>
<%= company_form.text_field :name, :size => 80 %>
<%= company_form.hidden_field :id %>
<% end -%>
</td>
<td>
<%= f.hidden_field :_destroy %>
<%= link_to_function "remove", "remove_co_fields(this)" %>
</td>
</tr>
当我更新现有记录时,一切正常。当我尝试使用新创建的记录保存表单时,我得到:
ActiveRecord::RecordNotFound in EventsController#update
Couldn't find Company with ID=12345 for CompanyEvent with ID=
使用stacktrace:
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:401:in `raise_nested_attributes_record_not_found'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:289:in `assign_nested_attributes_for_one_to_one_association'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:244:in `company_attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2906:in `send'
我查看了nested_attributes中的代码,并使用调试器运行它。发生的事情似乎是因为有一个Company.id,ActiveRecord假设已经有一个条目,但当然它找不到。这看起来很奇怪,因为显然我需要传入一个ID才能创建一个新的CompanyEvent条目。所以,我猜我错过了什么。
我发现这些例子似乎都是使用has_many关系一直嵌套,而在这种情况下它是一个belongs_to,我想知道这是否是问题的根源。任何想法将不胜感激......
答案 0 :(得分:13)
以下是我在类似问题中发布的另一种可能的解决方案:https://stackoverflow.com/a/12064875/47185
像这样......
accepts_nested_attributes_for :company
def company_attributes=(attributes)
if attributes['id'].present?
self.company = Company.find(attributes['id'])
end
super
end
答案 1 :(得分:4)
我遇到了同样的问题,看起来rails似乎不支持使用这样的嵌套模型:你不能用一个存在的嵌套模型保存一个新对象,例如想象这种情况:
class Monkey < ActiveRecord::Base
end
class Banana < ActiveRecord::Base
belongs_to :monkey
accepts_nested_attributes_for :monkey
end
如果您尝试使用控制台,这将不起作用:
banana = Banana.create!
monkey = Monkey.new
monkey.attributes = {:banana_attributes => { :id => banana.id}}
但是解决这个问题很简单,如果你的香蕉已经是持久的,你不需要在你的表单中设置任何嵌套属性,你只需要使用banana_id在猴子表单上有一个隐藏字段,这将导致类似的东西:
monkey.attributes = {:banana_id => banana.id}
这样可以保存得很好。