IIUCActiveSupport::XmlMini.backend = 'Nokogiri'
は、ReXML ではなく Nokogiri を使用して XML パラメータを解析するためのものであり、ビルダー テンプレートの生成用ではありません。
Nokogiri::XML::Builder を手動でrender
作成し、パーシャルの生成に依存しているため、出力は一貫しています。
以下を使用してください(config/initializers/nokogiri_builders.rb
実際にNokogiri
レンダー経由で使用するには(さらに、.xml.erb
ファイルの使用を停止して、独自のインスタンスを作成しNokogiri::XML::Builder
、単に使用すること.builder
もできます):
# config/initializers/nokogiri_builders.rb
# Using Nokogiri::XML::Builder in lieu of stock pure ruby Builder for Rails builder templates
module Nokogiri
module XML
class Builder
# handle instruct! instead of emitting nonsense tag
def instruct!(tag, options = {})
case tag
when :xml
@version = options[:version]
@encoding = options[:encoding]
else
raise NotImplementedError(tag.inspect)
end
end
# redefined, to recover what instruct! gave us
def to_xml(*args)
if Nokogiri.jruby?
options = args.first.is_a?(Hash) ? args.shift : {}
unless options[:save_with]
options[:save_with] = Node::SaveOptions::AS_BUILDER
end
args.insert(0, options)
end
if @version || @encoding
# set options according to what was given previously
args[0][:version] = @version if @version
args[0][:encoding] = @encoding if @encoding
# do emit a declaration
args[0].delete(:save_with)
end
@doc.to_xml(*args)
end
end
end
end
module ActionView
module Template::Handlers
class Builder
# Default format used by Builder.
class_attribute :default_format
self.default_format = :xml
def call(template)
require_engine
code = <<-CODE
builder = Nokogiri::XML::Builder.new do |xml|
#{template.source}
end
# default to not emit a declaration (use instruct! instead)
save_options = Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
# default to UTF-8, as it's Rails default encoding
options = { encoding: 'UTF-8', indent: 2, save_with: save_options }
self.output_buffer = builder.to_xml(options)
CODE
code
end
protected
def require_engine
@required ||= begin
require 'nokogiri'
true
end
end
end
end
end
Nokogiri は で出力を生成する前に完全な DOM を構築しますがto_xml
、Builder はその場で文字列を連結します。これは、特に大規模なデータ セットの場合、必要な場合とそうでない場合があります。ただし、どちらの場合も、最終的な文字列全体がメモリに常駐します。