<% form_for :project, :url => project_path(@project), :html => { :method => 'put' } do |f| %>
  <%= render :partial => 'fields', :locals => { :f => f } %>
  

<%= submit_tag "Update Project" %>

<% end %> <% form_for :project, :url => projects_path do |f| %> <%= render :partial => 'fields', :locals => { :f => f } %>

<%= submit_tag "Create Project" %>

<% end %>

Name: <%= f.text_field :name %>

<%= render :partial => 'task', :collection => @project.tasks %>
<%= add_task_link "Add a task" %>
<% fields_for "project[task_attributes][]", task do |f| %>

Task: <%= f.text_field :name, :index => nil %> <% if task.new_record? %> <%= link_to_function "remove", "$(this).up('.task').remove()" %> <% else %> <%= link_to_function "remove", "mark_for_destroy(this)" %> <%= f.hidden_field :id, :index => nil %> <%= f.hidden_field :should_destroy, :index => nil, :class => 'should_destroy' %> <% end %>

<% end %>
# models/project.rb class Project < ActiveRecord::Base has_many :tasks after_update :save_tasks validates_associated :tasks def task_attributes=(task_attributes) task_attributes.each do |attributes| if attributes[:id].blank? tasks.build(attributes) else task = tasks.detect { |t| t.id == attributes[:id].to_i } task.attributes = attributes end end end def save_tasks tasks.each do |t| if t.should_destroy? t.destroy else t.save(false) end end end end # models/task.rb class Task < ActiveRecord::Base belongs_to :project attr_accessor :should_destroy def should_destroy? should_destroy.to_i == 1 end end # projects_controller.rb def edit @project = Project.find(params[:id]) end def update @project = Project.find(params[:id]) if @project.update_attributes(params[:project]) flash[:notice] = "Successfully updated project." redirect_to projects_path else render :action => 'edit' end end /* application.js */ function mark_for_destroy(element) { $(element).next('.should_destroy').value = 1 $(element).up('.task').hide(); }