Я наконец-то решил это.Одним из ключей является аргумент коллекции fields_for .Другой - генерировать коллекцию из смеси существующих и новых записей.
Итак, в представлении что-то вроде:
<%= form_for @user do |f| %>
<table>
<tr><th>Completed</th><th>Time spent</th><th>Task</th></tr>
<%= f.fields_for :completions, available_completions_for_milestone(@user, @milestone) do |cf| %>
<tr>
<td><%= cf.check_box :status, {disabled: cf.object.persisted?}, "done", "unreported" %></td>
<td><%= cf.text_field :time_spent_text %></td>
<td><%= cf.object.task.description %></td>
</tr>
<%= cf.hidden_field :task_id %>
<% end -%>
С помощью вспомогательного метода:
def available_completions_for_milestone(user, milestone)
user_completions = user.completions.in_milestone(milestone)
available = []
milestone.tasks.each do |t|
c = user_completions.select{|c| c.task_id == t.id}.first
if !c then # make it
c = user.completions.build( task: t )
end
available << c
end
available
end
Обратите внимание на то, что дополнения, уже находящиеся в БД, проверяются и отключаются, поэтому их нельзя проверять.Не проверенное состояние получает значение «unreported», и модель User может отфильтровывать эти записи, чтобы они не помещались в БД:
has_many :completions
accepts_nested_attributes_for :completions, :reject_if => proc { |attrs| attrs['status'] == 'unreported' }
Я также должен был сделать completions_attributes
attr_accessible в модели User,Если вы сделаете task_ids
доступным, тогда update
удалит завершения, которые были исключены из PUT
.