# Recursive categories fetch and view

I have categories and subcategories in my view. The code looks like this

<ul>
<% Category.roots.each do |category| %>
<li class="col-md-2">
<a href="#"><%= category.name %></a>
<% if !category.children.empty? %>
<ul>
<%= category.decorate.draw_tree %>
</ul>
<% end %>
</li>
<% end %>
</ul>


I'm basically using a decorator to make it recursive

class CategoryDecorator < Draper::Decorator

delegate_all
decorates :category

def draw_tree

children.inject("") do |memo, child|

memo << "<li class=\"dir\"><a href=\"#\">#{child.name}</a>"
memo << "<ul>#{child.decorate.draw_tree}</ul>" if not child.children.empty?
memo << "</li>"

end.html_safe

end

end


It works fine. But I'm writing HTML inside a Ruby class and I don't like the idea, I'de like to keep it in the view. I tried to play with &block to turn it like following

<ul>
<% Category.roots.each do |category| %>
<li class="col-md-2">
<a href="#"><%= category.name %></a>
<% if !category.children.empty? %>
<ul>
<% category.decorate.draw_tree do |child| %>

<li class="dir"><a href="#"><%= child.name %></a>
<% if child.children.any %>
<ul><%= child.decorate.draw_tree %></ul>"
<% end %>
</li>"

<% end %>
</ul>
<% end %>
</li>
<% end %>
</ul>


Sadly, I couldn't make it work so far. I think I lack methodology here. How can I rewrite this code ?

Here's how I'd do it:

In your view, simply call a recursive method on each category:

<ul>
<% Category.roots.map do |category| %>
<%= draw_tree(category) %>
<% end %>
</ul>


And now in a helper file (app/helpers/category_helper.rb?), this is the "right" place to put HTML helpers. First, in pseudo-code:

def draw_tree(category)
<li class="col-md-2">
<a href="#"><%= category.name %></a>
<% category.children.each do |child| %>
<ul>
<%= draw_tree(child) %>
</ul>
<% end %>
</li>
end


Now, to actually make this work, rather than writing a string and calling #html_safe, a much cleaner (and generally safer) approach is to use content_tag. The end result is:

def draw_tree(category)
content_tag(:li, class: "col-md-2") do
category.children.map do |child|
content_tag(:ul, draw_tree(child))
end
end
end


I haven't actually run the above code, so apologies if there's some small mistake. But hopefully you get the idea :)

Working solution

The correct answer to my own question was the method content = capture { yield } which allows you to get the whole block content, so you can manipulate it entirely somewhere else and use recursivity.

I saw the answer in some random code after giving up to organize my code this way, a while ago.