Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 877569
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T11:37:51+00:00 2026-05-15T11:37:51+00:00

Partials in XML builder are proving to be non-trivial. After some initial Google searching,

  • 0

Partials in XML builder are proving to be non-trivial.

After some initial Google searching, I found the following to work, although it’s not 100%

 xml.foo do
     xml.id(foo.id)
     xml.created_at(foo.created_at)
     xml.last_updated(foo.updated_at)
     foo.bars.each do |bar|
         xml << render(:partial => 'bar/_bar', :locals => { :bar => bar })
     end
 end

this will do the trick, except the XML output is not properly indented. the output looks something similar to:

<foo>
  <id>1</id>
  <created_at>sometime</created_at>
  <last_updated>sometime</last_updated>
<bar>
  ...
</bar>
<bar>
  ...
</bar>
</foo>

The <bar> element should align underneath the <last_updated> element, it is a child of <foo> like this:

<foo>
  <id>1</id>
  <created_at>sometime</created_at>
  <last_updated>sometime</last_updated>
  <bar>
    ...
  </bar>
  <bar>
    ...
  </bar>
</foo>

Works great if I copy the content from bar/_bar.xml.builder into the template, but then things just aren’t DRY.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T11:37:52+00:00Added an answer on May 15, 2026 at 11:37 am

    There is unfortunately not a straight-forward solution to this. When looking at the code that ActionPack will initialize the Builder object with then the indent size is hard-coded to 2 and the margin size is not set. Its a shame that there is no mechanism to override this at present.

    The ideal solution here would be a fix to ActionPack to allow these options to be passed to the builder but this would require some time investment. I have 2 possible fixes for you. Both dirty you can take your pick which feels less dirty.

    Modify the rendering of the partial to render to a string and then do some Regex on it. This would look like this

    _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
    

    Note the gsub at the end of render line. This produces the following results

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

    That is a little hacky and definitely quite dirty but has the advantage of being contained within your code. The next solution is to monkey-patch ActionPack to get the Builder instance to work the way we want

    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
    

    This creates a new class at Rails initialisation called BuilderOptions whose sole purpose is to host 2 values for indent and margin (although we only really need the margin value). I did try adding these variable as class variables directly to the Builder template class but that object was frozen and I couldn’t change the values.

    Once that class is created we patch the compile method within the TemplateHandler to use these values.

    The template then looks as follows :-

    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
    

    The basic idea is to set the margin value to the indentation level that we are at when rendering the partial. The XML generated is identical to that shown above.

    Please do not copy/paste this code in without checking it against your Rails version to ensure that they are from the same codebase. (I think the above is 2.3.5)

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Given the following partial XML document: <section> <entry typeCode=DRIV> <act classCode=AT moodCode=DEF> <statusCode code=completed/>
I am parsing some vertice information from an XML file which reads as follows
I have the following XML (partial) document : <export> <table name=CLIENT> <row> <col name=CODE_CLIENT
I'm trying to hook up a blog with some xml namespaces and xml stylesheets.
Consider the following XML: <?xml version=1.0 encoding=ISO-8859-1?> <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>USA</COUNTRY>
I have the following complex type in my XML schema: <xs:complexType name=Widget mixed=true> <xs:sequence>
I have the following partial spring context xml file: <bean name=template class=org.springframework.jdbc.core.JdbcTemplate> <property name=dataSource
I have an xml file that I am parsing and I have the following
I'm transforming some XML from DrawingML to XAML. Unfortunately, the XAML one is not
I want to append the values of some XML tags, and then append again

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.