Il n'y a malheureusement pas de solution simple à cela. Lorsque vous regardez le code qu'ActionPack va initialiser l'objet Builder avec alors la taille de retrait est codée en dur à 2 et la taille de la marge n'est pas définie. C'est dommage qu'il n'y ait pas de mécanisme pour passer outre à cela à l'heure actuelle.
La solution idéale ici serait une solution à ActionPack pour permettre à ces options d'être transmises au constructeur, mais cela nécessiterait un investissement en temps. J'ai 2 corrections possibles pour vous. Les deux sales vous pouvez prendre votre choix qui se sent moins sale.
Modifiez le rendu du partiel à rendre à une chaîne, puis faites-lui une expression rationnelle. Cela ressemblerait à ceci
_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
Notez le gsub à la fin de la ligne de rendu. Cela produit les résultats suivants
<?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>
qui est un peu hacky et certainement assez sale, mais a l'avantage d'être contenu dans votre code.La solution suivante consiste à ActionPack singe-patch pour obtenir l'instance Builder pour travailler la façon dont nous voulons
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
Cela crée une nouvelle classe à l'initialisation Rails appelé BuilderOptions dont le seul but est d'héberger 2 valeurs pour le retrait et la marge (bien que nous ayons seulement vraiment besoin de la valeur de la marge). J'ai essayé d'ajouter ces variables de variable de classe directement à la classe de modèle Builder, mais cet objet était figé et je ne pouvais pas changer les valeurs. Une fois cette classe créée, nous patcherons la méthode de compilation dans TemplateHandler pour utiliser ces valeurs.
Le modèle ressemble à ce qui suit: -
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
L'idée de base est de définir la valeur de la marge au niveau de retrait que nous sommes à la partie lors du rendu. Le XML généré est identique à celui montré ci-dessus.
Veuillez ne pas copier/coller ce code sans le vérifier par rapport à votre version de Rails afin de vous assurer qu'ils proviennent du même code. (Je pense que ce qui précède est 2.3.5)
Ce problème est résolu dans Rails 4. – hcarreras