DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Acts As Tree Category Display
You should have a categories table with a parent_id field. Root categories should have the parent_id of 0.
I modified this post:
http://www.bigbold.com/snippets/posts/show/296
because the first one worked if you did stuff in your view to make the root categories come up, but I agree with the commenter that things should be contained to the helper - however I've managed to break the DRY rule in doing so. If anyone has any suggestions for a better way around this I'd love to hear it, so please comment. So anyway.. this should list your root categories ONLY and NOT your other sub-cats as well so that you have a very pretty little tree.
Slap this in your view:
<%= display_categories(@categories) %>
And put this in a helper file. You'll need it in the application helper most likely since you'll want to call it from multiple views.
def display_categories(categories)
ret = "<ul>"
for category in categories
if category.parent_id == 0
ret += "<li>"
ret += link_to category.name
ret += find_all_subcategories(category)
ret += "</li>"
end
end
ret += "</ul>"
end
def find_all_subcategories(category)
if category.children.size > 0
ret = '<ul>'
category.children.each { |subcat|
if subcat.children.size > 0
ret += '<li>'
ret += link_to h(subcat.name), :action => 'edit', :id => subcat
ret += find_all_subcategories(subcat)
ret += '</li>'
else
ret += '<li>'
ret += link_to h(subcat.name), :action => 'edit', :id => subcat
ret += '</li>'
end
}
ret += '</ul>'
end
end






Comments
Snippets Manager replied on Wed, 2009/04/29 - 11:33am
def display_tree_recursive(tree, category_id = nil, options = {}, &block) content_tag(:ul, options[:ul_options] || {}) do tree.inject('') do |output, node| output + (if node.category_id == category_id content_tag(:li, options[:li_options] || {}) do yield(node) + (node.children.empty? ? '' : display_tree_recursive(tree, node.id, &block)) end end || '') end end endSnippets Manager replied on Sat, 2006/08/12 - 1:26pm
def display_tree_recursive(tree, parent_id) ret = "\n" tree.each do |node| if node.parent_id == parent_id ret += "\n\t- "
ret += yield node
ret += display_tree_recursive(tree, node.id) { |n| yield n } unless node.children.empty?
ret += "\t
\n"
end
end
ret += "
\n" end Call from the view<%= display_tree_recursive(@tree, nil) { |node| node.name } %>The second paremter to the display_tree_recursive method is just the parent id you want to start from, my root doesn't have a parent_id so I just use the value nil.Snippets Manager replied on Sat, 2006/08/12 - 1:26pm
Brandon Aaron replied on Wed, 2006/06/07 - 6:35pm
ret += display_tree_recursive(tree, node.id) { |n| yield n }should be something along these lines to avoid invalid xhtml output:ret += display_tree_recursive(tree, node.id) { |n| yield n } unless node.children.size == 0Snippets Manager replied on Sun, 2006/05/28 - 7:40pm
def display_tree_recursive(tree, parent_id) ret = "And call it with a block:" tree.each do |node| if node.parent_id == parent_id ret += "- "
ret += yield node
ret += display_tree_recursive(tree, node.id) { |n| yield n }
ret += "
"
end
end
ret += "
" end<%= display_tree_recursive(@pages, 0) { |n| n.title } %>Snippets Manager replied on Sun, 2006/05/28 - 7:40pm
def display_tree_recursive(tree, parent_id) ret = "Just call it in your view with the 0 parent_id:" tree.each do |node| if node.parent_id == parent_id ret += "- "
ret += link_to node.title
ret += display_tree_recursive(tree, node.id)
ret += "
"
end
end
ret += "
" end<%= display_tree_recursive(@pages, 0) %>Snippets Manager replied on Sun, 2006/05/07 - 4:25am
@categories = Category.find( :all, :conditions => 'parent_id IS NULL', :include => [ { :children => [ :children, :parent ] }, :parent ] )This will get the first two levels of categories. Either that or you select all categories and handle the hierarchy yourself based strictly on id and parent_id values.