# _form.html.erb
<%= simple_form_for(@todo_list) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
</div>
<h3>Tasks</h3>
<table class='table'>
<thead>
<tr>
<th></th>
<th>Task Name</th>
<th>Completed</th>
</tr>
</thead>
<tbody class='tasks'>
<%= f.simple_fields_for :tasks do |builder| %>
<%= render 'task_fields', f: builder %>
<% end %>
</tbody>
</table>
<div class="form-actions">
<%= f.button :submit %>
<%= link_to_add_association 'Add Task', f, :tasks, class: 'btn btn-primary', data: { association_insertion_node: '.tasks', association_insertion_method: :append } %>
</div>
<% end %>
# _task_fields.html.erb
<tr class="nested-fields">
<td>
<%= link_to_remove_association "remove task", f, class: 'btn btn-primary btn-xs' %>
</td>
<td><%= f.input :description, label: false %></td>
<td><%= f.input :done, label: false %></td>
</tr>
# Gemfile
gem 'cocoon'
# application.js
//= require cocoon
# task.rb
class Task < ApplicationRecord
belongs_to :todo_list, optional: true
end
# todo_list.rb
class TodoList < ApplicationRecord
has_many :tasks, dependent: :destroy
accepts_nested_attributes_for :tasks,
allow_destroy: true,
reject_if: proc { |att| att['description'].blank? }
end
# todo_lists_controller.rb
def todo_list_params
params
.require(:todo_list)
.permit(:name, tasks_attributes: Task.attribute_names.map(&:to_sym).push(:_destroy))
end