1

I have a Category model which uses acts_as_tree

class Category < ActiveRecord::Base
  acts_as_tree :order=>"name"
end

When I display my category tree I use recursion, and an almost identical partial is generated each time (apart from some checkboxes being checked or not), requiring a large number of database calls.

I would like to cache this, but at the minute the only thing I can think of is by dumping Category.all in to a new non-ActiveRecord data structure to reduce the number of calls. Is there a better way?

index.html.erb

<%= render :partial=> "/categories/category_checkboxes", :locals=>{:select_categories=>@categories_ids} %>

_category_checkboxes.html.erb

<% @categories.each do |category| %>
    <h3><a href="#"><%=category.name%></a></h3>
    <div>
      <% category_children = category.children %>

      <%= render :partial => "/categories/category_checkbox_children",
                 :locals => { :child_categories => category_children, 
                              :chk_class=>chk_class, 
                              :select_categories=>select_categories } unless category_children.empty? %>
    </div>
<% end %>

_category_checkboxes_children.html.erb

<ul>
<% child_categories.each do |category| %>
  <li class= "category_check_box">
  <%=check_box_tag("category#{category.id}", 1, select_categories.index(category.id)%>
  <%=label_tag("category#{category.id}" ,"#{category.name}")%>
  <%= render :partial => "/categories/category_checkbox_children",  :locals => { 
                          :child_categories => category.children,
                          :select_categories=>select_categories} unless category_children.empty? %>
<% end %>
</li>
</ul>
David
  • 844
  • 6
  • 14

1 Answers1

1

The acts_as_tree gem is rather out of date. The last version (0.1.1) is from February 2010, and its functionality pretty limited.

I recommend you take a look at ancestry, a gem that provides similar functionality, and has added much more. Specifically, take a look at the section on Selecting nodes by depth.

rdvdijk
  • 4,400
  • 26
  • 30
  • That's great, and a better gem. I can select all the relevant nodes, but as soon as I take one of them and do .children it does another database call. Any solutions to this? – David Oct 02 '11 at 11:31
  • I'll try it out myself and see if it can do eager loading on the tree nodes. – rdvdijk Oct 02 '11 at 11:44
  • Have you tried using `subtree`? This does one query for the entire subtree under the current node. This works even without the depth caching. – rdvdijk Oct 02 '11 at 11:52
  • And even better, use: `node.subtree.arrange`. The `subtree` call retrieves all the nodes, and the `arrange` call puts them in a nested hash in the form of the tree. – rdvdijk Oct 02 '11 at 11:55
  • Now you're talking! Thanks :) – David Oct 02 '11 at 12:17