2012-03-24 3 views
2

Ich habe folgende Ruby-Skript:Nokogiri + ERB-Tag aus der Bestellung

require 'nokogiri' 
require 'erb' 

listing = %Q{<% listing "app/controllers/purchases_controller.rb", :id => "ch01_724" do %> 
foo 
<% end %>} 
erb = ERB.new(listing, nil, nil, "@output") 

def listing(title, attributes={}) 
    builder = Nokogiri::XML::Builder.new do |xml| 
    xml.example(attributes) do 
     xml.title "Listing 1.1 #{title}" 
     xml.programlisting do 
     yield 
     end 
    end 
    end 
    @output.concat(builder.doc.root.to_xml) 
end 

p erb.result(binding) 

Wenn es läuft, gibt er den folgenden Inhalt:

"\n  foo\n <example id=\"ch01_724\">\n <title>Listing 1.1 app/controllers/purchases_controller.rb</title>\n <programlisting/>\n</example>" 

Die "foo" Teil dieser Zeichenfolge sollte innerhalb des Elements programlisting sein, wird aber aus irgendeinem Grund dem Anfang der Zeichenfolge vorangestellt.

Warum ist das, und wie kann ich es beheben?

Antwort

6

Das liegt daran, dass Sie die ERB-Steuerung übergeben, die das "foo" erhält, und dann verketten Sie die Ausgabe der Methode danach.

Wie Rails ist dies mithilfe von Capture, die im Grunde den Ausgabepuffer für eine neue Zeichenfolge wechselt und dann diese neue Zeichenfolge verkettet.

Etwas Ähnliches scheint zu funktionieren:

def listing(title, attributes={}, &block) 
    builder = Nokogiri::XML::Builder.new do |xml| 
    xml.example(attributes) do 
     xml.title "Listing 1.1 #{title}" 
     xml.programlisting capture(&block) 
    end 
    end 
    @output.concat(builder.doc.root.to_xml) 
end 

def capture 
    @_out, @output = @output, "" 
    yield 
ensure 
    @output = @_out 
end 
+2

Das Wunder, dank Nicolás funktioniert! –