Question

Someone can explain me why content_tag have a different behavior in view and helpers? A simple code like the one below returns (1) when in the view, but (2) when in the Helper.

  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>

When using content_tag(:ul, '', :class => 'a class') in the Helper, it renders <ul class="a class"></ul>. Why this different behavior too?

The content_tag's behavior is very confusing. I tried some magic with the capture (another confusing method!) method, but without any success.

So... any ideas?

PS.: I'm using rails 4

-------------edit--------------

Since my example is really bad, what I'm really trying to do is somethind like that:

  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
Was it helpful?

Solution

This works form me...

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

Remove concat from first content_tag and add brackets into the inner concat method.

Update:

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

The same thing, you need to add brackets and remove the first concat to your code...

Update 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top