Как использовать вложенную форму для нескольких моделей в одной форме? - PullRequest
0 голосов
/ 06 мая 2010

Я изо всех сил пытаюсь найти правильный способ разработки формы, которая позволит мне вводить данные для двух разных моделей. Форма предназначена для «Инцидента», который имеет следующие отношения:

belongs_to              :customer
belongs_to              :user

has_one                 :incident_status

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

Таким образом, инцидент назначается «Клиенту» и «Пользователю», и пользователь может добавлять «Примечания» к инциденту. У меня проблемы с примечаниями в форме. Вот как отправляется форма:

{"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"}}}

Похоже, что он пытается добавить примечание об инциденте в качестве поля в поле «Инцидент», а не создавать новую запись в таблице инцидентных_отношений с внешним ключом инцидента_ид со ссылкой на инцидент.

Вот модель 'IncidentNote':

belongs_to :incident
belongs_to :user

Вот форма для «Инцидента»:

<% 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 %>

И, наконец, вот записи об инцидентах-контроллерах для New и Create.

Новое:

  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

Создать:

  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

Я не совсем уверен, где искать этот момент. Я уверен, что это всего лишь ограничение моего текущего навыка Rails (я не знаю много). Так что, если кто-то может указать мне правильное направление, я был бы очень признателен. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация!

Спасибо!

1 Ответ

1 голос
/ 06 мая 2010

Проверьте API для fields_for метода и перейдите к разделу «один ко многим».

Ваша модель имеет много :incident_notes, а не одну заметку об инциденте, поэтому она не понимает отношения и пытается найти поле с таким именем.

Так и должно быть:

  <% f.fields_for :incident_notes do |inote_form| %>
    <%= inote_form.label :note, 'Add a Note' %>
    <%= inote_form.text_area :note, :cols => 40, :rows => 20 %>
  <% end %>

Он просматривает все примечания об инцидентах, назначенные инциденту, и создает поля для каждого из них.
Вы также должны создать хотя бы одну заметку в своем действии new, иначе ее не будет:

  def new
    @incident = Incident.new
    @incident.incident_notes.build
    # ...
  end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...