I would like to get full nested (multiple levels) forms working with awesome_nested_set. Currently I've got one level working by adapting Ryans example from his Railscast: http://railscasts.com/episodes/197-nested-model-form-part-2
In my test app I have categories and I would like to go three levels deep eg: Categories -- Sub Category ---- Sub sub Category
Here is my code which works for adding Categories and Sub categories in one form:
category.rb (model)
class Category < ActiveRecord::Base
acts_as_nested_set
accepts_nested_attributes_for :children, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
named_scope :all_nested, :order => "lft"
end
categories_controller.rb (make_resources just simplifies the controller) class CategoriesController < ApplicationController make_resourceful do actions :all
before :index do
@categories = Category.all_nested
end
before :new do
3.times { @category.children.build }
end
end
end
_form.html.haml - form_for(@category) do |f| = f.error_messages %p = f.label :name = f.text_field :name
- f.fields_for :children do |builder|
= render "child_fields", :f => builder
= link_to_add_fields "Add Sub Category", f, :children
%p
= f.submit
_child_fields.html.haml %p#fields = f.label :name, "Sub Category Name:" = f.text_field :name = link_to_remove_fields "remove", f
application_helper.rb module ApplicationHelper def link_to_remove_fields(name,f) f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)") end
def link_to_add_fields(name,f,association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end
end
application.js (jquery) function remove_fields(link){ $(link).prev("input[type=hidden]").val("1"); $(link).closest("#fields").hide(); }
function add_fields(link, association, content){
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).before(content.replace(regexp, new_id));
}
The problem is that in Ryans example he has different names for the associations as they are separate models but in my case it's all referring to the same model as it's nested. I can get away with this for the first level as the children association loads the child_fields partial.
The problem is the third level.
Note: I'm using Rails 2.3.8, jquery 1.4.2, haml and awesome_nested_set