从父表单创建一定数量的子对象

时间:2010-01-21 16:24:41

标签: ruby-on-rails forms parent-child

感谢Ruby on Rails: How to gather values for child tables from a form?和“Agile Web Dev”,我知道如何使用fields_for在表单中包含多个模型。但是我在这个上面撕裂我的头发。

假设我有一个模型PersonPerson具有name属性和has_many :foos。反过来,Foo模型具有colour属性。

此外,我知道每个Person都有正好三个 Foos。我的模型,new中的createPersonController操作以及new视图应该是什么样子才能呈现三个标记精美的文本输入框,一个用于每个Foo并且能够报告验证错误,允许我的“新人”表单一次创建整个四个对象集合?

另外,我可以在没有accepts_nested_attributes_for的情况下执行此操作吗?

1 个答案:

答案 0 :(得分:3)

在玩了一些方形括号和不同的循环的不同位置之后,我想我已经解决了这个问题。以下是我的代码现在的样子(根据脚手架设置路线,以便从/new发布create}。

模型/ person.rb

class Person < ActiveRecord::Base
  has_many :foos
  validates_presence_of :name
end

模型/ foo.rb

class Foo < ActiveRecord::Base
  belongs_to :person
  validates_presence_of :colour
  validates_uniqueness_of :colour, :scope => "person_id"
end

控制器/ people_controller.rb

def new
  # Set up a Person with 3 defaulted Foos
  @person = Person.new
  (1..3).each { |i| @person.foos.build }
end

def create
  # Create (but don't save) a Person as specified
  @person = Person.new(params[:person])

  # Create (but don't save) a Foo for each set of Foo details
  @foos = []
  params[:foo].each do |foo_param|
    @foos << Foo.new(foo_param)
  end

  # Save everything in a transaction
  Person.transaction do
    @person.save!
    @foos.each do |foo|
      foo.person = @person
      foo.save!
    end
  end

  redirect_to :action => 'show', :id => @person

rescue ActiveRecord::RecordInvalid => e
  @foos.each do |foo|
    foo.valid?
  end
  render :action => 'new'
end

视图/人/ new.html.erb

<% form_for :person do |f| %>
  <%= error_messages_for :object => [@person] + @person.foos %>

  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>

  <table>
  <% @person.foos.each_with_index do |foo, index| @foo = foo%>
    <tr>
      <td><%= label :colour, "Foo colour #{index + 1}: " %></td>
      <td><%= text_field("foo[]", "colour" %></td>
    </tr>          
  <% end %>
  </table>

  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

这似乎可以解决问题。