Rails: Unable to nest content_tag

ruby-on-rails, ruby-on-rails-3, ruby-on-rails-3.2

Solution

This is the solution:

content_tag(:ul) do
  [1, 2].map do |x|
    content_tag(:li, x) <<
    content_tag(:ul) do
      ['a', 'b'].map do |y|
        content_tag(:li, y) <<
        content_tag(:ul) do
          ['i', 'ii'].map do |z|
            content_tag(:li, z)
          end.join('').html_safe
        end
      end.join('').html_safe
    end
  end.join('').html_safe
end

The problem is that you must return an HTML safe string at the end of each `content_tag` block:

# returns <li>asd</li>
content_tag('li') { 'asd' }

# returns <ul><li>asd</li></ul>
content_tag('ul') { content_tag('li') { 'asd' } }

# returns [1, 2]
[1, 2].each{ |x| content_tag('li', x) }

# returns ["<li>1</li>", "<li>2</li>"]
[1, 2].map{ |x| content_tag('li', x) }

# returns "<li>1</li><li>2</li>" not marked as HTML safe, 
# because `join` generates a new string
[1, 2].map{ |x| content_tag('li', x) }.join('')

# returns "<li>1</li><li>2</li>" marked as HTML safe
[1, 2].map{ |x| content_tag('li', x) }.join('').html_safe

# returns "<ul><li>1</li><li>2</li></ul>"
content_tag('ul') do
  [1, 2].map{ |x| content_tag('li', x) }.join('').html_safe
end

# returns "<ul><li>1</li><li>2</li></ul>"
content_tag('ul') do
  content_tag('li') { 'asd' } # this is ignored, since it is not returned
  [1, 2].map{ |x| content_tag('li', x) }.join('').html_safe
end

# returns "<ul><li>asd</li><li>1</li><li>2</li></ul>"
content_tag('ul') do
  content_tag('li') { 'asd' } <<
    [1, 2].map{ |x| content_tag('li', x) }.join('').html_safe
end

Problem

I have written a Rails helper to create a nested HTML list. However, this is not rendering correctly. What am I doing wrong please? Helper ``` content_tag :ul do [1, 2].each do |x| content_tag(:li, x) content_tag :ul do ['a', 'b'].each do |y| content_tag(:li, y) content_tag :ul do ['i', 'ii'].each do |z| content_tag(:li, z) end end end end end end ``` Expected output ``` <ul> <li>1</li> <ul> <li>a</li> <ul> <li>i</li> <li>ii</li> </ul> <li>b</li> <ul> <li>i</li> <li>ii</li> </ul> <li>2</li> <ul> <li>a</li> <ul> <li>i</li> <li>ii</li> </ul> <li>b</li> <ul> <li>i</li> <li>ii</li> </ul> </ul> </ul> ``` Actual output ``` <ul></ul> ```

Original source