残念ながら、これに対する簡単な解決策はありません。ActionPackがBuilderオブジェクトを初期化するコードを見ると、インデントサイズは2にハードコードされており、マージンサイズは設定されていません。現在、これを無効にするメカニズムがないのは残念です。
ここでの理想的な解決策は、これらのオプションをビルダーに渡すことができるようにActionPackを修正することですが、これにはある程度の時間の投資が必要になります。私はあなたのために2つの可能な修正を持っています。どちらも汚れているので、汚れが少ないと感じるものを選ぶことができます。
文字列にレンダリングするようにパーシャルのレンダリングを変更してから、正規表現を実行します。これはこのようになります
_bar.xml.builder
xml.bar do
xml.id(bar.id)
xml.name(bar.name)
xml.created_at(bar.created_at)
xml.last_updated(bar.updated_at)
end
foos / index.xml.builder
xml.foos do
@foos.each do |foo|
xml.foo do
xml.id(foo.id)
xml.name(foo.name)
xml.created_at(foo.created_at)
xml.last_updated(foo.updated_at)
xml.bars do
foo.bars.each do |bar|
xml << render(:partial => 'bars/bar',
:locals => { :bar => bar } ).gsub(/^/, ' ')
end
end
end
end
end
レンダリング行の最後にあるgsubに注意してください。これにより、次の結果が得られます
<?xml version="1.0" encoding="UTF-8"?>
<foos>
<foo>
<id>1</id>
<name>Foo 1</name>
<created_at>2010-06-11 21:54:16 UTC</created_at>
<last_updated>2010-06-11 21:54:16 UTC</last_updated>
<bars>
<bar>
<id>1</id>
<name>Foo 1 Bar 1</name>
<created_at>2010-06-11 21:57:29 UTC</created_at>
<last_updated>2010-06-11 21:57:29 UTC</last_updated>
</bar>
</bars>
</foo>
</foos>
これは少しハッキーで間違いなくかなり汚いですが、コードに含まれているという利点があります。次の解決策は、ActionPackにモンキーパッチを適用して、Builderインスタンスを希望どおりに動作させることです。
config / initializers / builder_mods.rb
module ActionView
module TemplateHandlers
class BuilderOptions
cattr_accessor :margin, :indent
end
end
end
module ActionView
module TemplateHandlers
class Builder < TemplateHandler
def compile(template)
"_set_controller_content_type(Mime::XML);" +
"xml = ::Builder::XmlMarkup.new(" +
":indent => #{ActionView::TemplateHandlers::BuilderOptions.indent}, " +
":margin => #{ActionView::TemplateHandlers::BuilderOptions.margin});" +
"self.output_buffer = xml.target!;" +
template.source +
";xml.target!;"
end
end
end
end
ActionView::TemplateHandlers::BuilderOptions.margin = 0
ActionView::TemplateHandlers::BuilderOptions.indent = 2
これにより、Railsの初期化でBuilderOptionsと呼ばれる新しいクラスが作成されます。このクラスの唯一の目的は、インデントとマージンの2つの値をホストすることです(ただし、実際にはマージン値のみが必要です)。これらの変数をクラス変数としてBuilderテンプレートクラスに直接追加しようとしましたが、そのオブジェクトがフリーズし、値を変更できませんでした。
そのクラスが作成されたら、これらの値を使用するようにTemplateHandler内のコンパイルメソッドにパッチを適用します。
テンプレートは次のようになります:-
xml.foos do
@foos.each do |foo|
xml.foo do
xml.id(foo.id)
xml.name(foo.name)
xml.created_at(foo.created_at)
xml.last_updated(foo.updated_at)
xml.bars do
ActionView::TemplateHandlers::BuilderOptions.margin = 3
foo.bars.each do |bar|
xml << render(:partial => 'bars/bar', :locals => { :bar => bar } )
end
ActionView::TemplateHandlers::BuilderOptions.margin = 0
end
end
end
end
基本的な考え方は、マージン値を、パーシャルをレンダリングするときのインデントレベルに設定することです。生成されるXMLは、上記のXMLと同じです。
同じコードベースからのものであることを確認するために、Railsのバージョンと照合せずにこのコードをコピーして貼り付けないでください。(上記は2.3.5だと思います)