我有以下型号:
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 %>
这是有点工作的,但它只是感觉不对,并且没有像铁路一样。此外,它会创建重复的记录,但我还没有能够删除记录。
有人能建议更好的方法吗?或者帮我重构一下我已有的东西?
答案 0 :(得分:0)
我没有时间写完整的答案,但要点是你想用fields_for
输出对象的关联字段。这也将在Rails中称为“嵌套模型表单”。
查看这些资源以获得一些帮助:
Nested Model Form Railscast
Rails API fields_for
答案 1 :(得分:0)
这就是我最终解决它的方式。
合并@ 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触发隐藏字段以删除记录。
如果您需要更多详细信息,请与我们联系。