32

我正在使用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

在我看来,我正在这样做:

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

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

有没有办法只为该注册创建一个新的注释,而不管现有的?

4

4 回答 4

78

编辑:我之前的回答(见下文)困扰着我,因为它不是很好(它仍然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 时添加文本区域(即尚未保存)。

另外,我实际上首先对此进行了测试,并且确实有效;)

于 2013-02-14T22:14:29.530 回答
4

如果你想在你的编辑操作上创建一个新的注册表单,你可以实例化一个新的 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

于 2013-02-14T22:04:50.530 回答
4

非常感谢您的帮助,正如我在帖子中所说的那样,“Zaid Crouch”(我不知道如何引用用户呵呵)的方法的唯一问题是,如果表单有错误字段,则表单页面重新加载后会变得清晰和繁荣,您的表单中不会填写任何内容,您能想象如果您的表单是 20 或 30 个字段,那当然会是糟糕的用户体验

这是我适用于验证模型的解决方案:

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,如果您想看到与验证和事务相同的工作,请查看此处的完整帖子:http: //elh.mx/ruby/using-simple_form-for-nested-attributes-models -in-a-has_many-relation-for-only-new-records/

于 2015-06-10T17:20:23.930 回答
3

正如 Heriberto Perez 正确指出的那样,如果其中一个字段出现验证错误,最受好评的答案中的解决方案将简单地丢弃所有内容。

我的方法与 Heriberto 的方法类似,但还是有点不同:

模型:

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 %>
于 2018-02-13T11:32:59.610 回答