How to use a nested form for multiple models in one form?

Posted by Magicked on Stack Overflow See other posts from Stack Overflow or by Magicked
Published on 2010-05-06T15:06:25Z Indexed on 2010/05/07 2:38 UTC
Read the original article Hit count: 302

Filed under:

I'm struggling to come up with the proper way to design a form that will allow me to input data for two different models. The form is for an 'Incident', which has the following relationships:

belongs_to              :customer
belongs_to              :user

has_one                 :incident_status

has_many                :incident_notes
accepts_nested_attributes_for :incident_notes, :allow_destroy => false

So an incident is assigned to a 'Customer' and a 'User', and the user is able to add 'Notes' to the incident. I'm having trouble with the notes part of the form. Here how the form is being submitted:

{"commit"=>"Create",
 "authenticity_token"=>"ECH5Ziv7JAuzs53kt5m/njT9w39UJhfJEs2x0Ms2NA0=",
 "customer_id"=>"4",
 "incident"=>{"title"=>"Something bad",
 "incident_status_id"=>"2",
 "user_id"=>"2",
 "other_id"=>"AAA01-042310-001",
 "incident_note"=>{"note"=>"This is a note"}}}

It appears to be attempting to add the incident_note as a field under 'Incident', rather than creating a new entry in the incident_note table with an incident_id foreign key linking back to the incident.

Here is the 'IncidentNote' model:

belongs_to :incident
belongs_to :user

Here is the form for 'Incident':

<% form_for([@customer,@incident]) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :other_id, "ID" %><br />
    <%= f.text_field :capc_id %>
  </p>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
    <p>
      <%= label_tag 'user', 'Assign to user?' %>
      <%= f.select :user_id, @users.collect {|u| [u.name, u.id]} %>
    </p>
    <p>
      <%= f.label :incident_status, 'Status?' %>
      <%= f.select :incident_status_id, @statuses.collect {|s| [s.name, s.id]} %>
    </p>
    <p>
      <% f.fields_for :incident_note do |inote_form| %>
        <%= inote_form.label :note, 'Add a Note' %>
        <%= inote_form.text_area :note, :cols => 40, :rows => 20 %>
      <% end %>
    </p>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

And finally, here are the incident_controller entries for New and Create.

New:

  def new
    @customer = current_user.customer
    @incident = Incident.new
    @users = @customer.users
    @statuses = IncidentStatus.find(:all)
    @incident_note = IncidentNote.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @incident }
    end
  end

Create:

  def create
    @users = @customer.users
    @statuses = IncidentStatus.find(:all)
    @incident = Incident.new(params[:incident])
    @incident.customer = @customer
    @incident_note = @incident.incident_note.build(params[:incident_note])
    @incident_note.user = current_user

    respond_to do |format|
      if @incident.save
        flash[:notice] = 'Incident was successfully created.'
        format.html { redirect_to(@incident) }
        format.xml  { render :xml => @incident, :status => :created, :location => @incident }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @incident.errors, :status => :unprocessable_entity }
      end
    end
  end

I'm not really sure where to look at this point. I'm sure it's just a limitation of my current Rails skill (I don't know much). So if anyone can point me in the right direction I would be very appreciative. Please let me know if more information is needed!

Thanks!

© Stack Overflow or respective owner

Related posts about ruby-on-rails