Creating a set number of child objects from a parent's form

久未见 提交于 2020-01-13 18:54:30

问题


Thanks to Ruby on Rails: How to gather values for child tables from a form? and "Agile Web Dev", I know how to have multiple models in a form using fields_for. But I'm tearing my hair out over this one.

Suppose I have a model Person. Person has a name attribute, and has_many :foos. The Foo model, in turn, has a colour attribute.

Furthermore, I know that each Person has precisely three Foos. What should my Models, the new and create actions in PersonController, and the new view look like in order to present three nicely-labelled text-entry boxes, one for each Foo and capable of reporting validation errors, to allow my "new person" form to create the whole set of four objects in one go?

Also, can I do this without accepts_nested_attributes_for?


回答1:


After some playing about with varied locations for square braces and different for loops, I think I've solved this. Here's what my code looks like now (with routes set up as per scaffolding, so that posting from /new triggers create).

models/person.rb

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

models/foo.rb

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

controllers/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

views/people/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 %>

This seems to do the trick.



来源:https://stackoverflow.com/questions/2110857/creating-a-set-number-of-child-objects-from-a-parents-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!