closure_tree
closure_tree copied to clipboard
Is there an efficient way of calling .depth on a list of items?
I'm trying to build a drop-down list which shows the hierarchy of my categories. So far I have this:
class Hash
def flatten_nested; flat_map{|k, v| [k, *v.flatten_nested]} end
end
<%= select_tag :category_id,
options_for_select(
Category.hash_tree.flatten_nested.map { |c| ['- ' * c.depth + c.name, c.id] },
params[:category_id]
), { include_blank: true, class: 'category-filter chosen-select', :'data-placeholder' => 'Filter by category' }
%>
It looks "good enough", at least the "- " prefix sort of shows the outline of the hierarchy.
The issue is that calling .depth
triggers an additional SQL query per item.
Is there a more efficient way in this library to order the nodes by hierarchy, and to also know what their depth is?
The only other thing I could think of was caching the depth property on the model.
Try just Category.all.map { |c| ['- ' * c.depth + c.name, c.id] }
@asgeo1 It seems like what you want is a better hash_tree—like, instead of the stringified name of the node, an actual object that contains more than just the name. That seems pretty useful! I'll think about it.
@yurgon calling .map on a scope will cause a query to be performed for every item, and calling Category.all will load every item in the database into memory. Both are very much not recommended.
How about select id, parent_id, name, (select max(generations) from division_hierarchies where descendant_id=divisions.id) as depth from divisions
@hooverlunch this helped me a lot! thanks! 💛