# How to better generalize a tree?

**URL:** <https://www.ruby-forum.com/t/how-to-better-generalize-a-tree/72675>\
**Category:** Rails\
**Created:** [February 24, 2006, 5:05am UTC](https://www.ruby-forum.com/t/how-to-better-generalize-a-tree/72675 "2006-02-24T05:05:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dana\_Pieluszczak](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ac8455/32.png) [@Dana\_Pieluszczak](https://www.ruby-forum.com/u/Dana_Pieluszczak)\
**Post date:** [February 24, 2006, 5:05am UTC](https://www.ruby-forum.com/t/how-to-better-generalize-a-tree/72675/1 "2006-02-24T05:05:09Z")

</div>

first some background info:  
I have a blog application that has a comments table with the following  
columns:  
id  
parent\_id  
post\_id  
created\_at  
body

here’s my model:

class Comment \< ActiveRecord::Base  
belongs\_to :post  
acts\_as\_tree :order =\> ‘created\_at’

def print\_children (options={})  
before = options[:before] ? options[:before]  
: ‘’  
after = options[:after] ? options[:after]  
: ‘’  
before\_children = options[:before\_children] ?  
options[:before\_children] : ‘’  
after\_children = options[:after\_children] ?  
options[:after\_children] : ‘’

```
output = ''

for child in children
  output += before
  output += child.body
  if !child.children.empty?
    output += before_children
    output += child.print_children options
    output += after_children
  end
  output += after
end
return output

```

end  
end

the print\_children method takes several options, for example, in my  
view it call it like:

\<% for comment in @comments %\> - \<%= comment.body %\> \<% if !comment.children.empty? %\> 
 \<%= comment.print\_children :before =\> ' - ', :after =\> '
', :before\_children =\> '
', :after\_children =\> '
' %\> 
 \<% end %\> 
\<% end %\>

@comments is an array of all the comments for the current post where  
parent\_id is null (each of those potentially has a tree of comments  
beneath it)  
that will give me all the comments in nice nested lists.

Now for the question. Is there a way to make something like this use a  
partial template, such that, for each comment, I could render a  
template, instead of passing several options to print\_children? The  
way it works now, if i want to display more comment properties (for  
example, created\_at, or in the future, the author) or if i wanted to  
format each comment in some odd way I have to change both my template  
AND my print\_children method.

-Dana

---

<div class="post-metadata">

**Author:** ![Dana\_Pieluszczak](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ac8455/32.png) [@Dana\_Pieluszczak](https://www.ruby-forum.com/u/Dana_Pieluszczak)\
**Post date:** [February 25, 2006, 6:32am UTC](https://www.ruby-forum.com/t/how-to-better-generalize-a-tree/72675/2 "2006-02-25T06:32:23Z")

</div>

The solution is to use a recursive partial template, this keeps all the  
display code in view where it belongs.

the model:  
class Comment \< ActiveRecord::Base  
belongs\_to :post  
acts\_as\_tree :order =\> ‘created\_at’  
end

the main template:

 \<% for comment in @comments %\> \<%= render :partial =\> 'comment', :locals =\> {:comment =\> comment} %\> \<% end %\>

and the partial template (\_comment.rhtml), notice how it renders itself:

- 
 \<%= comment.body %\> 
 \<% if !comment.children.empty? %\> 
 \<% for comment in comment.children %\> \<%= render :partial =\> 'comment', :locals =\> {:comment =\> comment } %\> \<% end %\> 
 \<% end %\>

---

<div class="post-metadata">

**Author:** ![Dana\_Pieluszczak](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/ac8455/32.png) [@Dana\_Pieluszczak](https://www.ruby-forum.com/u/Dana_Pieluszczak)\
**Post date:** [February 25, 2006, 8:12am UTC](https://www.ruby-forum.com/t/how-to-better-generalize-a-tree/72675/3 "2006-02-25T08:12:50Z")

</div>

Dana wrote:  
I can’t believe I wrote the same kind of code today. I chose to use the  
:collection member of the options hash to let Rails iterate the  
collections. This just happens to be my application – a menu tree –  
but it looks pretty much like any other kind of tree:)

BTW: This can be also accomplished very nicely with Builder::XmlMarkup  
used in a simple recursion.

template:

 \<%= render :partial =\> 'menu\_list', :collection =\> @menus %\>

partial:

- \<%= menu\_list.menu\_name %\> \<% if menu\_list.has\_children? -%\> 
 \<%= render(:partial =\> 'menu\_list', :collection =\> menu\_list.children) %\> 
\<% end -%\>

> the main template:
> 
> \<% for comment in @comments %\> \<%= render :partial =\> 'comment', :locals =\> {:comment =\> comment} %\> \<% end %\>
> 
> and the partial template (\_comment.rhtml), notice how it renders itself:
> 
> - 
> \<%= comment.body %\> 
> \<% if !comment.children.empty? %\> 
> \<% for comment in comment.children %\> \<%= render :partial =\> 'comment', :locals =\> {:comment =\> comment } %\> \<% end %\> 
> \<% end %\>
