30

我正在尝试一个辅助方法,它将输出一个项目列表,像这样调用:

foo_list( ['item_one', link_to( 'item_two', '#' ) ... ] )

在阅读Using helpers in rails 3 to output html之后,我已经像这样编写了助手:

def foo_list items
    content_tag :ul do
        items.collect {|item| content_tag(:li, item)}
    end
end

但是,如果我将其作为测试,那么在这种情况下我只会得到一个空的 UL:

def foo_list items
    content_tag :ul do
        content_tag(:li, 'foo')
    end
end

我按预期获得了 UL 和 LI。

我已经尝试将它交换一下:

def foo_list items
    contents = items.map {|item| content_tag(:li, item)}
    content_tag( :ul, contents )
end

在那种情况下,我得到了整个列表,但 LI 标记是 html 转义的(即使字符串是 HTML 安全的)。做content_tag(:ul, contents.join("\n").html_safe )的工作,但对我来说感觉不对,我觉得content_tag应该以某种方式在块模式下使用集合。

4

5 回答 5

54

尝试这个:

def foo_list items
  content_tag :ul do
      items.collect {|item| concat(content_tag(:li, item))}
  end
end
于 2011-01-12T21:07:50.703 回答
8

我无法更好地完成这项工作。

如果你已经在使用HAML,你可以这样写你的助手:

def foo_list(items)
  haml_tag :ul do
    items.each do |item|
      haml_tag :li, item
    end
  end
end

从视图的用法:

- foo_list(["item_one", link_to("item_two", "#"), ... ])

输出将是正确的。

于 2011-01-12T18:19:45.160 回答
5

您可以使用content_tag_for,它适用于集合:

def foo_list(items)
  content_tag(:ul) { content_tag_for :li, items }
end

更新:在 Rails 5中content_tag_for(和div_for)被移动到一个单独的 gem 中。您必须安装record_tag_helpergem 才能使用它们。

于 2013-07-02T16:38:58.660 回答
4

除了上面的答案,这对我很有用:

(1..14).to_a.each do |age|
  concat content_tag :li, "#{link_to age, '#'}".html_safe
end
于 2015-06-09T14:35:29.133 回答
2

The big issue is that content_tag isn't doing anything smart when it receives arrays, you need to send it already processed content. I've found that a good way to do this is to fold/reduce your array to concat it all together.

For example, your first and third example can use the following instead of your items.map/collect line:

items.reduce(''.html_safe) { |x, item| x << content_tag(:li, item) }

For reference, here is the definition of concat that you're running into when you execute this code (from actionpack/lib/action_view/helpers/tag_helper.rb).

def concat(value)
  if dirty? || value.html_safe?
    super(value)
  else
    super(ERB::Util.h(value))
  end
end
alias << concat
于 2011-11-28T22:56:11.430 回答