【问题标题】:Need to create and update attributes on join model of has_many through relationship需要通过关系在 has_many 的连接模型上创建和更新属性
【发布时间】:2013-09-15 17:11:06
【问题描述】:

我有以下型号:

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

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

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

【问题讨论】:

    标签: ruby-on-rails-3 ruby-on-rails-3.2 nested-attributes has-many-through jointable


    【解决方案1】:

    这就是我最终解决它的方法。

    结合@carlos 的输入,我使用 Ryan Bates 的助手动态添加新的nested_attributes 字段,但将其更改为在我的城市列表中工作

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

    关键在于使用 if 语句检查记录是新记录还是现有记录,然后在 fields_for 帮助器上正确设置 child_index:。

    我还必须使用 check_box_tag 而不是 .check_box 帮助器,这样它就不会产生隐藏的复选框字段。

    当用户取消选中访问城市旁边的框时,我使用 Javascript 触发隐藏字段删除记录。

    如果您需要更多详细信息,请与我们联系。

    【讨论】:

    • 太好了,很高兴看到我的指点将您引向了正确的方向!
    【解决方案2】:

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

    查看这些资源以获得帮助:
    Nested Model Form Railscast
    Rails API fields_for

    【讨论】:

    • 我曾考虑过这一点,但我看不出如何配置它,以便城市模型驱动表单中的列表,而不是仅列出针对该个人记录的所有现有访问。
    • 查看 Railscast 第 2 部分,railscasts.com/episodes/…,了解有关在表单中即时添加新城市的动态链接的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    相关资源
    最近更新 更多