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

时间:2022-10-27 12:47:33

I'm trying a helper method that will output a list of items, to be called like so:

我正在尝试一个助手方法,它将输出一个项目列表,被调用如下:

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

I have written the helper like so after reading Using helpers in rails 3 to output html:

在使用rails 3中的helper函数输出html后,我编写了类似的助手:

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

However I just get an empty UL in that case, if I do this as a test:

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

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

I get the UL & LI as expected.

我按预期得到了UL & LI。

I've tried swapping it around a bit doing:

我试着交换一下

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

In that case I get the whole list but the LI tags are html escaped (even though the strings are HTML safe). Doing content_tag(:ul, contents.join("\n").html_safe ) works but it feels wrong to me and I feel content_tag should work in block mode with a collection somehow.

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

5 个解决方案

#1


45  

Try this:

试试这个:

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

#2


7  

I couldn't get that work any better.

我找不到更好的工作了。

If you were using HAML already, you could write your helper like this:

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

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

Usage from view:

使用视图:

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

Output would be correctly intended.

输出应该是正确的。

#3


5  

You could use content_tag_for, which works with collections:

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

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

Update: In Rails 5 content_tag_for (and div_for) were moved into a separate gem. You have to install the record_tag_helper gem in order to use them.

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

#4


3  

Along with answers above, this worked for me well:

除了以上的答案,这对我很有效:

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

#5


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.

最大的问题是,当content_tag接收到数组时,它并没有做任何聪明的事情,您需要将已经处理好的内容发送给它。我发现一个很好的方法是折叠/减少你的数组,把它们结合在一起。

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

作为参考,这里是您在执行该代码时遇到的concat的定义(来自actionpack/lib/action_view/helper /tag_helper.rb)。

def concat(value)
  if dirty? || value.html_safe?
    super(value)
  else
    super(ERB::Util.h(value))
  end
end
alias << concat

#1


45  

Try this:

试试这个:

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

#2


7  

I couldn't get that work any better.

我找不到更好的工作了。

If you were using HAML already, you could write your helper like this:

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

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

Usage from view:

使用视图:

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

Output would be correctly intended.

输出应该是正确的。

#3


5  

You could use content_tag_for, which works with collections:

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

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

Update: In Rails 5 content_tag_for (and div_for) were moved into a separate gem. You have to install the record_tag_helper gem in order to use them.

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

#4


3  

Along with answers above, this worked for me well:

除了以上的答案,这对我很有效:

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

#5


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.

最大的问题是,当content_tag接收到数组时,它并没有做任何聪明的事情,您需要将已经处理好的内容发送给它。我发现一个很好的方法是折叠/减少你的数组,把它们结合在一起。

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

作为参考,这里是您在执行该代码时遇到的concat的定义(来自actionpack/lib/action_view/helper /tag_helper.rb)。

def concat(value)
  if dirty? || value.html_safe?
    super(value)
  else
    super(ERB::Util.h(value))
  end
end
alias << concat