2

我有以下三个模型(Rails 2.3.8)

    class Outbreak < ActiveRecord::Base
        has_many :incidents, :dependent => :destroy
        has_many :locations, :through => :incidents

        accepts_nested_attributes_for :incidents, :allow_destroy => true
        accepts_nested_attributes_for :locations, :allow_destroy => true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }

    end

   class Incident < ActiveRecord::Base
        belongs_to :outbreak
        belongs_to :location
   end


   class Location < ActiveRecord::Base
 has_many :incidents
 has_many :outbreaks, :through => :incidents

     accepts_nested_attributes_for :incidents, :allow_destroy => true

   end

表单中的参数似乎还可以

"爆发"=>{ "locations_attributes"=>{"0"=>{"lon"=>"-1.39", "placename"=>"wetwe", "hpu_id"=>"15", "postcode"= >"so1 1aa", "region_id"=>"10", "address_1"=>"", "town"=>"Bargate", "address_2"=>"", "address_3"=>"", "lat "=>"50.89"}},"incidents_attributes"=>{"0"=>{"subtype_id"=>"7", "category_id"=>"1", "detail"=>"", "subcategory_id" =>“2”}} }

但是,当保存爆发时,在 Incidents 表(连接表)中创建了 3 行,在 Outbreak 和 Location 表中创建了一行。

Incidents 表中的行未完全从参数填充,如下所示:

id outbreak_id location_id category_id subcategory_id subtype_id detail  created_at    updated_at 

 57 23   NULL     1       2           7                          2010-11-25 14:45:18.385905  2010-11-25 14:45:18.385905 
 58 23   27         NULL       NULL        NULL    NULL           2010-11-25 14:45:18.39828  2010-11-25 14:45:18.39828 
 59 23   27         NULL         NULL     NULL      NULL           2010-11-25 14:45:18.403051  2010-11-25 14:45:18.403051 

这一定是由于参数的格式或多个 accept_nested_attributes_for 方法造成的 - 如何在 Incidents 表中只输入一行包含所有参数信息?

4

2 回答 2

4

本周到目前为止,我已经第二次回答了我自己的问题^^,这将教会我在放弃并在网上发帖寻求帮助之前付出更多的努力,

仍然在查看我最初的问题之后,我没有包含足够的信息来正确回答它 - 问题(除了模型的设置)归结为爆发控制器新方法中的爆发构造函数,

原始 Outbreaks_controller

def new

    @outbreak = Outbreak.new
    @outbreak.risks.build
    //links locations directly to Outbreak instead of through Incidents
    @outbreak.locations.build
    @outbreak.incidents.build

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

修订的 Outbreaks_controller

def new

    @outbreak = Outbreak.new
    @outbreak.risks.build
    //builds Incidents then a Location through that incident
    @outbreak.incidents.build.build_location

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

三个模型的变化

    class Outbreak < ActiveRecord::Base
        has_many :incidents, :dependent => :destroy
        has_many :locations, :through => :incidents

        accepts_nested_attributes_for :incidents, :allow_destroy => true


    end

   class Incident < ActiveRecord::Base
        belongs_to :outbreak
        belongs_to :location

        accepts_nested_attributes_for :location, :allow_destroy => true
   end


   class Location < ActiveRecord::Base
       has_many :incidents
       has_many :outbreaks, :through => :incidents

   end

这似乎工作正常 - 还发布了创建操作和主表单

于 2010-11-26T11:37:03.887 回答
1

创建操作只需要为 :outbreak 提供的嵌套参数(模型完成工作)。

def create

    @outbreak = Outbreak.new(params[:outbreak])
    @outbreak.user_id = current_user.id

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

爆发表格很长,因此我将其缩减为提到的两个部分(尽管此处的属性和字段可能比需要了解的要多)。

嵌套字段的 HTML 元素 id 的示例可以在 Javascript observe_field 帮助器的底部找到。我在nested_attributes_for partials 的AJAX 更新上发表的帖子也可能对accepted_nested_attributes_for 的AJAX 更新有用

    <% form_for(@outbreak, :html => {:multipart => true}) do |form| %>
    <%= form.error_messages %>
    <div id="tabs">
        <ul>

            <li ><a href="#tabs_b">Outbreak</a></li>
            <li ><a href="#tabs_c">Location</a></li>

        </ul>   


            <div id="tabs_b">
                <fieldset id="b" class="form_div">
                    <legend>Outbreak</legend>

                    <fieldset>
                        <legend>References</legend>
                      <div class="left_form">
                        <%= form.label :user_reference %>
                      </div>
                      <div class="right_form">
                        <%= form.text_field :user_reference %>
                      </div>
                      <div style="clear:both;"></div>

                    </fieldset>

                </fieldset>
            </div>
            <div id="tabs_c">
                <fieldset id="c" class="form_div" >

                    <legend>Location</legend>
                      <div id="location_error"></div>
                            <fieldset>
                            <legend>Setting</legend>
                <% form.fields_for :incidents do |incident_form| %>

                                  <div class="left_form">
                                    <%= incident_form.label :category_id %>
                                  </div>

                                  <div class="right_form">
                                    <div id="incident_category_select">
                                    <%= render :partial => 'category_select', :locals => {:categories => @categories, :incident_form => incident_form} %>
                                    </div>
                                  </div>
                                  <div style="clear:both;"></div>

                                  <div class="left_form">
                                    <%= incident_form.label :subcategory_id %>
                                  </div>
                                  <div class="right_form">
                                    <div id="incident_subcategory_select">
                                    <%= render :partial => 'subcategory_select', :locals => { :subcategories => @subcategories, :incident_form => incident_form } %>
                                    </div>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= incident_form.label :subtype_id %>
                                  </div>
                                  <div class="right_form">
                                    <div id="incident_subtype_select">
                                    <%= render :partial => 'subtype_select',  :locals => { :subtypes => @subtypes, :incident_form => incident_form } %>
                                    </div>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div id="cuisine_div">
                                    <% if @outbreak.outbreak_type == "FOODBORNE" %>
                                        <div class="left_form">
                                            <%= label :incident, :cuisine_id %>
                                        </div>
                                        <div class="right_form">
                                            <% cuisine_select = (@incident != nil ? @incident.cuisine_id.to_i : '') %>
                                            <%= incident_form.select( :cuisine_id, "<option value='' >Please select</option>" + options_from_collection_for_select(@cuisines, :id, :name, cuisine_select)) %>
                                        </div>
                                    <% end %>

                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= incident_form.label :detail %>
                                  </div>
                                  <div class="right_form">
                                    <%= incident_form.text_field :detail %>
                                  </div>


                        </fieldset>
                        <fieldset>
                            <legend>Details</legend>
                            <%  incident_form.fields_for :location do |location_form| %>
                                  <div style="clear:both;"></div>
                                   <div class="left_form">
                                    <%= location_form.label :placename %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :placename %>
                                  </div> 
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :address_1 %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :address_1 %>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :address_2 %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :address_2 %>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :address_3 %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :address_3 %>
                                  </div> 
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :town %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :town %>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :postcode %>
                                  </div>
                                  <div class="right_form">
                                    <%= location_form.text_field :postcode %>
                                  </div>
                                  <div style="clear:both;"></div>        
                                  <div class="left_form">
                                    <%= location_form.label :region_id %>
                                  </div>
                                  <div class="right_form" >
                                        <% region_select = (@location != nil ? @location.region_id.to_i : '') %>
                                    <%= location_form.select(:region_id, "<option value=''>Select a region</option>" + options_from_collection_for_select(@regions, :id, :name, region_select)) %>
                                  </div>
                                  <div style="clear:both;"></div>
                                  <div class="left_form">
                                    <%= location_form.label :hpu_id %>
                                  </div>
                                  <div class="right_form" >
                                    <% hpu_select = (@location != nil ? @location.hpu_id.to_i : '') %>
                                    <%= location_form.select(:hpu_id, "<option value=''>Select a HPU</option>" + options_from_collection_for_select(@hpus, :id, :name, hpu_select)) %>
                                  </div>
                                  <div style="clear:both;"></div>

                                <%= location_form.hidden_field :lon, :value => '' %>
                                <%= location_form.hidden_field :lat, :value => '' %>
                                <%= hidden_field_tag :postcode_error, :value => '0' %>
                                <% end %>
                          </fieldset>


                    <% end %>       

                </fieldset>

            </div>


    </div>
    <% end %>

    <div style="clear: both; margin: 10px;"></div>
    <%= observe_field(:outbreak_incidents_attributes_0_location_attributes_postcode, 
              :url => { :controller => :locations, :action => :find_lonlat },
              :on => "onchange",
              :loading => "Element.show('loader')",
              :success => "Element.hide('loader')",
              :with => "'postcode=' + encodeURIComponent($('outbreak_incidents_attributes_0_location_attributes_postcode').value)" ) %>
于 2010-12-02T15:07:04.340 回答