循环&在helper中的content_tag中输出content_tags

时间:2011-01-12 13:53:32

标签: ruby-on-rails ruby-on-rails-3 helper block

我正在尝试一个帮助方法,它将输出一个项目列表,如下所示:

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&李如预期。

我已经尝试过将其交换一下:

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应该以某种方式在某个集合模式下工作。

5 个答案:

答案 0 :(得分:49)

试试这个:

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

答案 1 :(得分: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", "#"), ... ])

输出是正确的。

答案 2 :(得分: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_helper gem才能使用它们。

答案 3 :(得分:3)

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

(1..14).to_a.each do |age|
  concat content_tag :li, "#{link_to age, '#'}".html_safe
end

答案 4 :(得分:2)

最大的问题是,在收到数组时,content_tag没有做任何聪明的事情,你需要发送已处理过的内容。我发现这样做的一个好方法是折叠/缩小你的数组以便将它们连接在一起。

例如,您的第一个和第三个示例可以使用以下内容代替您的items.map/collect行:

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

作为参考,这里是执行此代码时遇到的concat的定义(来自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