Loop & output content tags within content tag in helper

Próbuję metody helpera, która wyświetli listę elementów, które mają być wywołane w ten sposób:

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

Napisałem helpera tak po przeczytaniu używając helperów w rails 3 do wyjścia html :

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

Jednak po prostu dostaję pusty UL w takim przypadku, jeśli zrobię to jako test:

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

Dostaję UL & LI zgodnie z oczekiwaniami.

Próbowałem go trochę podmienić robiąc:

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

W takim przypadku dostaję całą listę, ale znaczniki LI są HTML (chociaż łańcuchy są bezpieczne dla HTML). Robienie content_tag(:ul, contents.join("\n").html_safe ) działa, ale wydaje mi się to złe i czuję, że content_tag powinno działać w trybie blokowym z kolekcją.

Author: Community, 2011-01-12

5 answers

Spróbuj tego:

def foo_list items
  content_tag :ul do
      items.collect {|item| concat(content_tag(:li, item))}
  end
end
 46
Author: zetetic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 21:07:50

Nie mogłem znaleźć lepszej pracy.

Jeśli już używałeś HAML , możesz napisać swojego pomocnika TAK:

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

Użycie z widoku:

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

Wyjście byłoby poprawnie zaplanowane.

 7
Author: Heikki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 18:19:45

You could use content_tag_for, który współpracuje ze zbiorami:

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

Update: W Rails 5 content_tag_for (i div_for) zostały przeniesione do osobnego klejnotu. Musisz zainstalować record_tag_helper gem, aby z nich korzystać.

 5
Author: Daniel Rikowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 08:06:14

Wraz z odpowiedziami powyżej, to działało dla mnie dobrze:

(1..14).to_a.each do |age|
  concat content_tag :li, "#{link_to age, '#'}".html_safe
end
 3
Author: The Whiz of Oz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 14:35:29

Duży problem polega na tym, że content_tag nie robi nic mądrego, gdy odbiera tablice, musisz wysłać już przetworzoną zawartość. Odkryłem, że dobrym sposobem na to jest złożenie / zmniejszenie tablicy, aby połączyć to wszystko razem.

Na przykład, twój pierwszy i trzeci przykład może używać następujących elementów zamiast twoich przedmiotów.linia map/collect:

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

Dla odniesienia, oto definicja concat, na którą się natkniesz podczas wykonywania tego kodu (z 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
 2
Author: billmag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-29 00:04:35