Nokogiri + ERB тег из заказа - PullRequest
2 голосов
/ 25 марта 2012

У меня есть следующий скрипт на Ruby:

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)

При запуске он выводит следующее содержимое:

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

Часть "foo" этой строки должна находиться внутриЭлемент programlisting, но вместо этого, по какой-то причине, имеет префикс к началу строки.

Почему это так и как я могу это исправить?

1 Ответ

6 голосов
/ 25 марта 2012

Это потому, что, передавая управление, вы передаете управление в ERB, который получает «foo», а затем вы объединяете выходные данные метода.

Как Rails делает это с помощью захвата, который в основном переключает выходной буфер для новой строки, а затем объединяет эту новую строку.

Что-то вроде этого работает:

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
...