content_tag 行为在视图和助手中不同

Posted

技术标签:

【中文标题】content_tag 行为在视图和助手中不同【英文标题】:content_tag behavior different in view and helper 【发布时间】:2013-09-26 01:22:46 【问题描述】:

有人可以解释一下为什么 content_tag 在视图和助手中有不同的行为吗?像下面这样的简单代码在视图中返回 (1),但在 Helper 中返回 (2)。

  arr = ["a", "b", "c"]
  concat content_tag(:ul, :class => 'a class') do
    arr.each do |item|
      concat content_tag(:li, item)
    end
  end

(1)

<ul class="a class">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

(2)

<ul>:class=&gt;"a class"</ul>

当在 Helper 中使用 content_tag(:ul, '', :class =&gt; 'a class') 时,它会呈现 &lt;ul class="a class"&gt;&lt;/ul&gt;。为什么会有这种不同的行为?

content_tag 的行为非常令人困惑。我尝试了使用 capture(另一种令人困惑的方法!)方法的一些魔法,但没有任何成功。

那么……有什么想法吗?

PS.:我正在使用 Rails 4

----------编辑--------------

由于我的例子真的很糟糕,我真正想做的是这样的事情:

  def language_dropdown
    content_tag :li, class: "dropdown language" do
      concat content_tag(:a, content_tag(:span, I18n.locale, class: "username"),
                     class: "dropdown-toggle", data:  toggle: "dropdown", hover: "dropdown", "close-others" => "true"  )

      concat( content_tag(:ul, class: "dropdown-menu") do
        I18n.available_locales.each do |locale|
          if locale != I18n.locale
            locale_key = "translation.#locale"
            content_tag :li do
              concat(link_to I18n.t(locale_key), url_for(locale: locale.to_s))
            end
          end
        end
      end)
    end.html_safe
  end

【问题讨论】:

【参考方案1】:

这对我有用...

module ApplicationHelper
  def some_helper arr
    content_tag(:ul, :class => 'a class') do
      arr.each do |item|
        concat(content_tag(:li, item))
      end
    end
  end
end

从第一个 content_tag 中删除 concat 并将括号添加到内部 concat 方法中。

更新:

content_tag :li, class: "dropdown language" do
  concat(content_tag(:a,content_tag(:span, I18n.locale, class: "username"),
    class: "dropdown-toggle", data:  toggle: "dropdown", hover: "dropdown", "close-others" => "true" ))
  concat(content_tag(:ul, class: "dropdown-menu")
    I18n.available_locales.each do |locale|
      if locale != I18n.locale
        locale_key = "translation.#locale"
        concat(content_tag(:li)link_to(I18n.t(locale_key), url_for(locale: locale.to_s)))
      end
    end
  )
end

同样的事情,你需要在你的代码中添加括号并删除第一个 concat...

更新 2:

items = ""
I18n.available_locales.each do |locale|
  if locale != I18n.locale
    locale_key = "translation.#locale"

    items += content_tag(:li) do
      link_to(I18n.t(locale_key), url_for(locale: locale.to_s))
    end
  end
end

label = content_tag(:span, I18n.locale, class: "username")
link = content_tag(:a, label, class: "dropdown-toggle",
    data:  toggle: "dropdown", hover: "dropdown", "close-others" => "true" )

content_tag :li, class: "dropdown language" do
  concat(link)
  concat(content_tag(:ul, class: "dropdown-menu") items.html_safe )
end

【讨论】:

嗯不错。看起来我把 concat 放在了错误的地方。好像有点乱,还有其他更好的方法吗?

以上是关于content_tag 行为在视图和助手中不同的主要内容,如果未能解决你的问题,请参考以下文章

内容标签(已修改):第2部分(视图)

在 helper 的 content_tag 中循环和输出 content_tags

视图和部分助手的示例

asp.net 5 MVC6 中标签助手和路由属性之间的奇怪行为

(简单)Ror:在视图中创建助手。但是怎么做?

将值从视图传递给助手