Creating the specified number of children from the parent form

Thanks to Ruby on Rails: how to collect values ​​for child tables from a form? and "Agile Web Dev", I know how to have several models in using fields_for. But I take my hair off of it.

Suppose I have a model Person. Personhas the attribute nameand has_many :foos. The model Foo, in turn, has an attribute colour.

In addition, I know that everyone Personhas exactly three Foos. What my models, actions, newand createin PersonControllerand presentation should do newto present three beautifully labeled text input fields, one for each Foo and capable of reporting validation errors to allow my “new person” form to create a whole set of four objects at a time ?

Also, can I do this without accepts_nested_attributes_for?

+3
source share
1 answer

, , . ( , /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 %>

.

+3

Source: https://habr.com/ru/post/1729414/


All Articles