Kategorien (per Ancestry) als verschachtelte HTML Liste
Heute stellte sich mir die Aufgabe eine per Ancestry in der Datenbank gespeicherte Kategorie-Baumstruktur als verschachtelte HTML-Liste darzustellen.
Hier die Darstellung des Kategorie-Baums:
- Kategorie 1 - Sub-Kategorie 1 - Sub-Kategorie 2 - Kategorie 2 - Sub-Kategorie 3 - Sub-Kategorie 4 - Kategorie 3 - Sub-Kategorie 5 - Sub-Kategorie 6 - SubSub-Kategorie
Dank Ryan Bates fantastischem Railscast über Ancestry hatte ich schon einen Ansatz für einen Helper, den ich wie unten etwas modifizierte.
module CategoriesHelper def nested_categories(categories) categories.map do |category, sub_categories| if sub_categories.present? content_tag(:li, h(category.name) + content_tag(:ul, nested_categories(sub_categories), nil, false), nil, false) else content_tag(:li, h(category.name), nil, false) end end.join.html_safe end end
Die Schwierigkeit dabei war, dass die verschachtelten “content_tag” das HTML doppelt escaped haben. Zum Glück kann man escape auf false setzen. Achtung! Wichtig dabei ist allerdings, dass ihr alle kritischen Ausgaben wieder manuell mit h() escaped. Eure Seite wird sonst anfällig auf Cross-Site-Scripting Angriffe. Speziell wenn ihr euren Usern gestattet Inhalte auf eure Seite zu schreiben. Aber auch bei Content-Management-Systemen (CMS) ist es von Vorteil, wenn die vom Autor eingegebenen Zeichen gegebenenfalls konvertiert werden, um valides HTML auszuliefern.
Der Aufruf im View erfolgt folgendermaßen:
<%= content_tag :ul, nested_categories(@categories.arrange(:order => :position)), :class => "categories" %>
Und voilà! Das Ergebnis:
<ul class="categories"> <li>Kategorie 1 <ul> <li>Sub-Kategorie 1</li> <li>Sub-Kategorie 2</li> </ul> </li> <li>Kategorie 2 <ul> <li>Sub-Kategorie 3</li> <li>Sub-Kategorie 4</li> </ul> </li> <li>Kategorie 3 <ul> <li>Sub-Kategorie 5</li> <li>Sub-Kategorie 6 <ul> <li>SubSub-Kategorie</li> </ul> </li> </ul> </li> </ul>
Es freut mich wenn ich auch nur einem Webentwickler da draußen damit helfen konnte. Schreibt mir eure Erfahrungen!