如何获得Rails构建和fields_for只创建一个新记录而不包括现有记录?

我使用buildfields_foraccepts_nested_attributes_for在与新注册相同的表单上创建新的注册注释(有许多注册注释)。 大。

问题:在现有注册的编辑表单上,我想要创建另一个新的注册注释,但我不希望看到每个现有注册注释的字段。

我有这个

 class Registration < ActiveRecord::Base attr_accessible :foo, :bar, :registration_notes_attributes has_many :registration_notes accepts_nested_attributes_for :registration_notes end 

还有这个

 class RegistrationsController < ApplicationController def edit @registration = Registration.find(params[:id]) @registration.registration_notes.build end end 

在我看来我这样做:

        

它正在为新的注册记录(好)创建一个空白文本区域,并为该注册创建每个现有的注册记录(不,谢谢)。

有没有办法只为该注册创建一个新注释并保留现有注释?

编辑 :我之前的回答(见下文)是困扰我,因为它不是很好(它仍然不必要地循环所有其他registration_notes )。 在阅读了API之后,获得OP所需行为的最佳方法是替换:

 <%= r.fields_for :registration_notes do |n| %> 

有:

 <%= r.fields_for :registration_notes, @registration.registration_notes.build do |n| %> 

fields_for可选地接受第二个参数,该参数是要传递给构建器的特定对象( 请参阅API ),该构建器是内联构建的。 实际上,在控制器中创建和传递新音符可能更好,而不是在表单中传递(只是为了将逻辑移出视图)。


原始答案(我是如此接近):

只是为了澄清,您希望您的编辑表单包含一个新的嵌套注册注释(并忽略任何其他现有注册注释)? 我没有测试过这个,但你应该可以通过替换:

  <%= r.fields_for :registration_notes do |n| %> 

有:

  <%= r.fields_for @registration.registration_notes.build do |n| %> 

编辑 :好的,从我自己的快速测试不起作用,但你可以这样做:

 <%= r.fields_for :registration_notes do |n| %> <%= n.text_area :content if n.object.id.nil? %> <% end %> 

如果注册注释的id为nil(即尚未保存),则仅添加文本区域。

另外,我实际上先测试了它,它确实有效;)

如果要在编辑操作上创建新的注册表单,可以只实例化一个新的registration_note对象。 现在,您的表单是针对现有的注册对象。

我相信这就是你想要的:

 class RegistrationsController < ApplicationController def edit @new_registration_note = RegistrationNote.new @registration = Registration.find(params[:id]) @registration.registration_notes.build end end 

在您的视图中,您应该传递一个引用注册记录ID的隐藏参数:

 <%= form_for @new_registration_note do |r| %> <%= r.hidden_field :registration_id, :value => @registration.id %> <%= r.text_area :content %> <% end %> 

现在,您可以创建属于 @registration新注册注释。 确保registration_notes表中有一列指向注册。 您可以在此处阅读有关协会的更多信息: http : //guides.rubyonrails.org/association_basics.html

非常感谢你的帮助,正如我在post中所说的那样,来自“Zaid Crouch”(我不知道如何引用用户hehe)的方法的唯一问题是,如果表单有错误字段表单页面重新加载后你会清楚并且繁荣,你的表单中没有任何内容,你能想象如果你的表单就像20或30个字段那样会是一个糟糕的用户体验当然

这是我的解决方案,适用于validation模型:

 class Registration < ActiveRecord::Base attr_accessible :foo, :bar, :registration_notes_attributes has_many :registration_notes has_one :new_registration, class_name: 'RegistrationNote' accepts_nested_attributes_for :new_registration end class RegistrationsController < ApplicationController def edit @registration = Registration.find(params[:id]) @registration.build_new_registration end end <%= form_for @registration do |r| %> <%= r.text_field :foo %> <%= r.text_field :bar %> <%= r.fields_for :new_registration do |n| %> <%= n.text_area :content %> <% end %> <% end %> 

我在我的例子中使用simple_form如果你想看到同样的validation和事务处理,请看一下完整的post: http : //elh.mx/ruby/using-simple_form-for-nested-attributes-models -in-A-的has_many-关系换只新-记录/

正如Heriberto Perez正确地指出,如果在其中一个字段上存在validation错误,那么最受欢迎的答案中的解决方案将简单地丢弃所有内容。

我的方法与赫里伯托相似,但有点不同:

模型:

 class Registration < ActiveRecord::Base has_many :registration_notes accepts_nested_attributes_for :registration_notes # Because 0 is never 1 this association will never return any records. # Above all this association don't return any existing persisted records. has_many :new_registration_notes, -> { where('0 = 1') } , class_name: 'RegistrationNote' accepts_nested_attributes_for :new_registration_notes end 

控制器:

 class RegistrationsController < ApplicationController before_action :set_registration def edit @registration.new_registration_notes.build end private def set_registration @registration = Registration.find(params[:id]) end def new_registration_params params.require(:registration).permit(new_registrations_attributes: [:content]) end end 

视图:

 <%= form_for @registration do |r| %> <%= r.text_field :foo %> <%= r.text_field :bar %> <%= r.fields_for :new_registration_notes do |n| %> <%= n.text_area :content %> <% end %> <% end %>