This time I would like to share a helper I wrote for rails. I was trying to write a form to add categories and I wanted to present a neatly formatted select box of existing categories to select as the parent category. It also needed infinite nested subcategories. I could not find a tutorial or example code anywhere for what I was trying to do. So I wrote this little snippet.

application_helper.rb:

 
  def tree_select(categories, model, name, selected=0, level=0, init=true)
    html = ""
    # The "Root" option is added
    # so the user can choose a parent_id of 0
    if init
        # Add "Root" to the options
        html << "<select name=\"#{model}[#{name}]\" id=\"#{model}_#{name}\">\n"
        html << "\t<option value=\"0\""
        html << " selected=\"selected\"" if selected.parent_id == 0
        html << ">Root</option>\n"
    end

    if categories.length > 0
      level += 1 # keep position
      categories.collect do |cat|
        html << "\t<option value=\"#{cat.id}\" style=\"padding-left:#{level * 10}px\""
        html << ' selected="selected"' if cat.id == selected.parent_id
        html << ">#{cat.name}</option>\n"
        html << tree_select(cat.children, model, name, selected, level, false)
      end
    end
    html << "</select>\n" if init
    return html
  end
 

View:

 
<%= tree_select(Category.find(:all, :conditions => "parent_id = 0"),
                        'category', 'parent_id', @category) %>
 

Tree Select Menu