Contents:
- show full path for the item
- show tree in ol li
- show tree in dropdown select
-
one item
-
list of items
show full path for each item
# controller
@items = Category.where(..).all
# cache categories - all categories by ids
@all_categories_hash = Category.unscoped.all.inject({}){|res, elem| res[elem.id] = elem; res }
# view
- @items.each do |item|
%h3= item.title
path:
= item.ancestor_ids.map{|x| @all_categories_hash[x].title}.join(' / ')
Our model is organized in tree using ancestry gem.
We want to show in view the full tree with nested elements (with ul, li) like that:
<ul>
<li>
Fruits
<ul>
<li>Apple</li>
<li>Orange</li>
</ul>
</li>
<li>
Vegetables
<ul>
<li>Tomato</li>
<li>Potato</li>
<li>Cabbage</li>
</ul>
</li>
</ul>
- model
class Category ..
end
-
Category has attribute 'title' which will be shown in a tree.
-
controller
def index
@items_tree = Category.all.arrange
end
- create a helper method
# app/helpers/application_helper.rb
def render_nested_groups(groups)
s = content_tag(:ul) do
groups.map do |group, sub_groups|
content_tag(:li, (group.title + nested_groups(sub_groups)).html_safe)
end.join.html_safe
end
end
- view
Use helper to present tree in view:
# app/views/categories/index.html.haml
= nested_groups(@items_tree)
- controller
def edit
@categories = collection_for_parent_select
end
def collection_for_parent_select
@categories = ancestry_options(Category.unscoped.arrange(:order => 'name')) {|i| "#{'-' * i.depth} #{i.name}" }
end
def ancestry_options(items)
result = []
items.map do |item, sub_items|
result << [yield(item), item.id]
#this is a recursive call:
result += ancestry_options(sub_items) {|i| "#{'-' * i.depth} #{i.name}" }
end
result
end
- form
= f.input :parent_id, :as => :select, :collection => @categories