2013-02-20 59 views
4

我写了一个Rails助手来创建一个嵌套的HTML列表。但是,这不能正确呈现。请问我做错了什么?Rails:无法嵌套content_tag

助手

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 

预期输出

<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> 

实际输出

<ul></ul> 
+0

'each'不会返回正确的价值;尝试用'map'代替它。 – mdesantis 2013-02-20 23:41:10

+0

我刚刚用'map'试过了,但输出结果是一样的。 – gjb 2013-02-20 23:44:49

回答

7

这是解决方案:

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 

的问题是,你必须在每个content_tag块的最后返回一个HTML安全的字符串:

# 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 
+0

这会产生一个错误:'语法错误,意外的tSYMBEG,期待keyword_do或'{'或'('content_tag:ul do' – gjb 2013-02-20 23:47:11

+0

对不起;我更正了答案 – mdesantis 2013-02-20 23:53:50

+1

谢谢你不仅提供解决方案,而且为了解释清楚为什么我的代码不工作。 – gjb 2013-02-21 10:07:45