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:
<ul>
<% for comment in @comments %>
<li>
<%= comment.body %>
<% if !comment.children.empty? %>
<ul>
<%= comment.print_children :before =>
''<li>'',
:after =>
''</li>'',
:before_children =>
''<ul>'',
:after_children =>
''</ul>'' %>
</ul>
<% end %>
</li>
<% end %>
</ul>
@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
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:
<div class="comments">
<ul>
<% for comment in @comments %>
<%= render :partial => ''comment'', :locals =>
{:comment => comment}
%>
<% end %>
</ul>
</div>
and the partial template (_comment.rhtml), notice how it renders itself:
<li>
<div>
<%= comment.body %>
</div>
<% if !comment.children.empty? %>
<ul>
<% for comment in comment.children %>
<%= render :partial => ''comment'', :locals =>
{:comment =>
comment } %>
<% end %>
</ul>
<% end %>
</li>
--
Posted via http://www.ruby-forum.com/.
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:
<ul>
<%= render :partial => ''menu_list'', :collection =>
@menus %>
</ul>
partial:
<li>
<%= menu_list.menu_name %>
<% if menu_list.has_children? -%>
<ul>
<%= render(:partial => ''menu_list'', :collection
=>
menu_list.children) %>
</ul>
<% end -%>
</li>
> the main template:
>
> <div class="comments">
> <ul>
> <% for comment in @comments %>
> <%= render :partial => ''comment'', :locals =>
{:comment => comment}
> %>
> <% end %>
> </ul>
> </div>
>
> and the partial template (_comment.rhtml), notice how it renders itself:
>
> <li>
> <div>
> <%= comment.body %>
> </div>
> <% if !comment.children.empty? %>
> <ul>
> <% for comment in comment.children %>
> <%= render :partial => ''comment'', :locals
=> {:comment =>
> comment } %>
> <% end %>
> </ul>
> <% end %>
> </li>
--
Posted via http://www.ruby-forum.com/.