2011-01-12 8 views
25

Ich versuche, eine Hilfsmethode, die eine Liste von Elementen ausgegeben, wie so genannt werden:Loop & Ausgang content_tags innerhalb content_tag in Helfer

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

Ich habe die Helfer wie so geschrieben Using helpers in rails 3 to output html nach der Lektüre:

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

jedoch habe ich eine leere UL nur in diesem Fall erhalten, wenn ich dies als Test tun:

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

Ich bekomme die UL & LI wie erwartet.

Ich habe versucht, es ein bisschen herum Swapping tun:

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

In diesem Fall bekomme ich die ganze Liste, aber die LI-Tags sind HTML entkommen (obwohl die Saiten HTML sicher). Doing content_tag(:ul, contents.join("\n").html_safe) funktioniert, aber es fühlt sich falsch an und ich fühle mich content_tag sollte im Block-Modus mit einer Sammlung irgendwie funktionieren.

Antwort

43

Try this:

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

Das funktioniert, ich hatte versucht, die concat um das Sammeln zu machen, vorher eher als innerhalb. Mit concat innerhalb des proc wird dann collect nicht benötigt und Sie können items.each (oder andere Iteratoren) verwenden. – DEfusion

+3

Auf diese Weise rufen Sie concat für jedes Element auf. Ich denke, dass es billiger wäre, items.collect {} zu machen. Join (""). Html_safe –

7

Ich konnte diese Arbeit nicht besser bekommen.

Wenn Sie HAML bereits verwendet haben, könnten Sie Ihre Helfer wie folgt schreiben:

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

Verwendung von Ansicht:

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

Ausgabe korrekt bestimmt werden würde.

+0

Danke, das ist super glatt! –

2

Das große Problem ist, dass content_tag nichts tut klug, wenn es Arrays empfängt, müssen Sie es bereits bearbeiteten Inhalte senden. Ich habe festgestellt, dass ein guter Weg, dies zu tun ist, falten/reduzieren Sie Ihr Array, um alles zusammen zu concat.

Zum Beispiel Ihres erstes und drittes Beispiel kann die anstelle Ihrer items.map/collect Linie folgenden verwenden:

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

Als Referenz hier ist die Definition von Concat, die Sie laufen in, wenn Sie Führe diesen Code aus (aus 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 
5

Sie könnten content_tag_for verwenden, die mit Sammlungen funktionieren:

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

Update: In Rails 5 content_tag_for (und div_for) wurden in ein separates Juwel bewegen. Sie müssen das record_tag_helper Juwel installieren, um sie zu verwenden.

+0

content_tag_for in Rails entfernt 5 – hellion

3

Zusammen mit Antworten oben, das ist für mich gut funktioniert:

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

Möglicherweise müssen Sie dann <% = bis <% in der Vorlage ändern. – nruth

Verwandte Themen