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) %>

February 21st, 2008 at 11:53 pm
Great helper! Thanks a lot!
March 15th, 2008 at 1:35 pm
Perfect - just what I was looking for!
April 15th, 2008 at 7:14 am
There’s nobody I like more than the man who saves me time. Great post. Thanks for writing the snippit.
December 23rd, 2008 at 11:55 am
really cool! thanx!
January 4th, 2009 at 11:57 pm
This tag works wonderfully when editing records within the Category table. However, I need help making it work on my Tag table. My Tag table
belongs_to :category
I can get the select menu to display the existing tree of Cateogries, but not to select the preset value in the Tag table record’s “category_id” cell.
Any help you can supply would be appreciated.
January 6th, 2009 at 11:03 am
I figured this out. I just removed your “def tree_select” from the “application_helper.rb” file, and then placed it elsewhere with minor edits as follows:
1) I put it on the “categories_helper.rb” just as you had written it, with your two references to “selected.parent_id”.
2) I then put a slightly modified version of it on the other “…_helper.rb” templates where I want to use it, but replaced the “selected.parent_id” with “selected.id”. You can leave it as “selected.parent_id”, but will see that it selects the next higher node on the tree branch.
Note that one must remove the code from the “application_helper.rb” in order for this distributed instance model to work.
Your code is very sweet, and I thank you muchly!
January 6th, 2009 at 11:53 am
Also, on the particular helper pages I replaced
html \n”
with hard-coded field “name” and “id”
html \n”
This one is for the “category_id” field on the “tag” helper.
February 21st, 2009 at 10:00 am
Thank you for your item.
Note: In Rails with SQLite3
:conditions => “parent_id = 0″
replace by this:
:conditions => “parent_id IS NULL “