0

我有以下型号:

class Individual < ActiveRecord::Base
  has_many visits
  has_many cities, :through => visits
  accepts_nested_attributes_for :visits, reject_if: proc { |a| a[:city_id].blank? }, allow_destroy: true
end

class Visit < ActiveRecord::Base
  belongs_to individual
  belongs_to city
end

class City < ActiveRecord::Base
  has_many visits
  has_many individuals, :through => visits
end

我正在尝试为每个人开发一个表格,列出我数据库中的所有城市,并允许他们勾选他们访问过的城市,然后添加一些关于该城市的基本属性。我目前拥有的是:

             <%= form_for(individual) do |f| %>
                  <% for city in cities.each do %>
                    <tr>
                      <td>
                          <%= check_box_tag "individual[visits_attributes][][city_id]", city_id.id, individual.cities.include?(city) %>
                      </td>
                      <td>
                        <label>How good was your visit here?</label>
                        <%= select_tag "individual[visits_attributes][][sentiment]", options_for_select([ ...... ])) %>
                      </td>
                      <td>
                        <label>What was the weather like?</label>
                        <%= select_tag "individual[visits_attributes][][weather]", options_for_select([ ...... ])) %>
                      </td>
                      <td>
                        <label>Where did you stay?</label>
                        <%= select_tag "individual[visits_attributes][][accomodation]", options_for_select([ ...... ])) %>
                      </td>
                    </tr>
                  <% end %>
                  <%= f.submit "Update", :class => "btn" %>
              <% end %>

这是一种工作方式,但它只是感觉不对劲而且不正常。此外,它会创建重复记录,我还无法让它删除记录。

任何人都可以提出更好的方法吗?或者帮我重构我已经拥有的东西?

4

2 回答 2

0

This is how I eventually solved it.

Incorporating @carlos's input I used Ryan Bates's helper for dynamically adding new nested_attributes fields but altered it to work in my list of cities

<%= form_for(individual) do |f| %>
  <% for city in cities.each do %>
    <% if individual.visits.include?(city) %>
      <% visit = f.object.visits.find_by_city_id(city.id) %>
      <%= f.fields_for(:visits, visit, child_index: visit.id ) do |existing_visit| %>
        <tr>
          <td>
              <%= check_box_tag "individual[visits_attributes][#{visit.id}][city_id]", city.id, individual.visits.include?(city) %>
              <%= existing_visit.hidden_field :_destroy %>
          </td>
          <td>
            <label>How good was your visit here?</label>
            <%= existing_visit.select :sentiment, options_for_select([ ...... ])) %>
          </td>
          <td>
            <label>What was the weather like?</label>
            <%= existing_visit.select :weather, options_for_select([ ...... ])) %>
          </td>
          <td>
            <label>Where did you stay?</label>
            <%= existing_visit.select :accomodation, options_for_select([ ...... ])) %>
          </td>
        </tr>
      <% end %>
    <% else %>
      <% visit = f.object.visits.build %>
      <% random_index = city.id.to_s+"_"+Time.now.to_i.to_s %>
      <%= f.fields_for(:visits, visit, child_index: random_index) do |new_visit| %>
        <tr>
          <td>
              <%= check_box_tag "individual[visits_attributes][#{random_index}][city_id]", city.id, nil %>
          </td>
          <td>
            <label>How good was your visit here?</label>
            <%= new_visit.select :sentiment, options_for_select([ ...... ])) %>
          </td>
          <td>
            <label>What was the weather like?</label>
            <%= new_visit.select :weather, options_for_select([ ...... ])) %>
          </td>
          <td>
            <label>Where did you stay?</label>
            <%= new_visit.select :accomodation, options_for_select([ ...... ])) %>
          </td>
        </tr>
      <% end %>
    <% end %>
    <%= f.submit "Update", :class => "btn" %>
  <% end %>
<% end %>

The key was in using an if statement to check whether the record was a new record or existing and then correctly setting the child_index: on the fields_for helper.

I also had to use the check_box_tag rather than .check_box helper so that it didn't produce the hidden check box field.

I use Javascript to trigger the hidden field to delete a record when the user unchecks the box next to the city that the visit took place.

Get in touch if you need more details.

于 2013-09-12T16:05:00.840 回答
0

我没有时间写一个完整的答案,但要点是你想用它fields_for来输出对象的关联字段。这在 Rails 中也被称为“嵌套模型表单”。

查看这些资源以获得一些帮助:
嵌套模型表单 Railscast
Rails API fields_for

于 2013-09-11T17:07:04.327 回答