<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SmartLogic Solutions Blog &#187; deep level associations</title>
	<atom:link href="http://blog.smartlogicsolutions.com/tag/deep-level-associations/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.smartlogicsolutions.com</link>
	<description>News and updates from the people at SmartLogic Solutions</description>
	<lastBuildDate>Tue, 30 Nov 2010 21:39:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Using ActiveRecord&#8217;s to_xml to produce custom xml including deep level associations</title>
		<link>http://blog.smartlogicsolutions.com/2008/09/10/using-activerecords-to_xml-to-produce-custom-xml-including-deep-level-associations/</link>
		<comments>http://blog.smartlogicsolutions.com/2008/09/10/using-activerecords-to_xml-to-produce-custom-xml-including-deep-level-associations/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 18:49:34 +0000</pubDate>
		<dc:creator>Glenn Gentzke</dc:creator>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Glenn Gentzke]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[deep level associations]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[to_xml]]></category>

		<guid isPermaLink="false">http://blog.smartlogicsolutions.com/?p=237</guid>
		<description><![CDATA[ActiveRecord provides a powerful method to all its records called to_xml. Most web developers using RoR should be familiar with its usage and hopefully use it for their simple xml production needs. But what do you do when you need to produce xml that is selective, includes associations, or contains custom tags? There are many [...]]]></description>
			<content:encoded><![CDATA[<p>ActiveRecord provides a powerful method to all its records called <strong>to_xml</strong>.  Most web developers using RoR should be familiar with its usage and hopefully use it for their simple xml production needs.  But what do you do when you need to produce xml that is selective, includes associations, or contains custom tags?  There are many ways to manipulate to_xml&#8217;s output and I&#8217;ll explain a few below.<br />
<span id="more-237"></span></p>
<h3>The Options Hash</h3>
<p>The most obvious way to change the output is to use the options hash <a href="http://api.rubyonrails.org/classes/ActiveRecord/XmlSerialization.html">outlined in the docs</a>.  A short list of options you might want to explore is:</p>
<ul>
<li>except => [:attr1, :attr2] &#8212; excludes attributes in array from output</li>
<li>only => [:attr1, :attr2] &#8212; output contains only the specified attributes</li>
<li>include	 => [:assoc1, :assoc2] &#8212; calls to_xml on the given first level association and nests it in the output</li>
<li>methods => [:meth1, :meth2] &#8212; adds a tag to output in the format <em>&lt;method-name&gt;[method output]&lt;/method-name&gt;</em></li>
</ul>
<p>Usage is incredibly simple:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># grab xml for a record and its child</span>
  my_record.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:child</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># same, but only output the ids and names (assuming both have these attributes)</span>
  my_record.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:only</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span>, :<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:child</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h3>Behold, the Builder</h3>
<p>A fantastic feature of to_xml that <a href="http://ryandaigle.com/articles/2007/4/13/what-s-new-in-edge-rails-a-more-flexible-to_xml">Ryan blogged about last year</a> is that it yields the builder, thus allowing you to add arbitrary tags into the output.  What&#8217;s more is you can pass the builder into another object&#8217;s to_xml method inside the outer block and produced nested xml.</p>
<p>For example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># Arbitrarily insert a tag</span>
  my_record.<span style="color:#9900CC;">to_xml</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>xml<span style="color:#006600; font-weight:bold;">|</span>
    xml.<span style="color:#9900CC;">some_tag</span> some_value   <span style="color:#008000; font-style:italic;">#=&gt; &lt;some_tag&gt;some_value&lt;/some_tag&gt;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># I want to get xml for my record and all its children</span>
  my_record.<span style="color:#9900CC;">to_xml</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>xml<span style="color:#006600; font-weight:bold;">|</span>
    my_record.<span style="color:#9900CC;">children</span>.<span style="color:#9900CC;">each</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>child<span style="color:#006600; font-weight:bold;">|</span> child.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> xml, <span style="color:#ff3333; font-weight:bold;">:skip_instruct</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>You can nest as deep as you want without overriding a model&#8217;s own to_xml method:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  output = my_record.<span style="color:#9900CC;">to_xml</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>xml<span style="color:#006600; font-weight:bold;">|</span>
    my_record.<span style="color:#9900CC;">children</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>child<span style="color:#006600; font-weight:bold;">|</span>
      child.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> xml, <span style="color:#ff3333; font-weight:bold;">:skip_instruct</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>fxml<span style="color:#006600; font-weight:bold;">|</span>
        child.<span style="color:#9900CC;">grandchild</span>.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> fxml, <span style="color:#ff3333; font-weight:bold;">:skip_instruct</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>deep_xml: Model methods that utilize (but do not overwrite) to_xml</h3>
<p>I chose to write methods in the models that handled including the children&#8217;s xml such that a single call to my_record.full_xml would produce nested xml automatically.  Notice how the builder is being passed to the children, it&#8217;s important!</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">class</span> ParentClass <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
    has_many <span style="color:#ff3333; font-weight:bold;">:children</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> deep_xml<span style="color:#006600; font-weight:bold;">&#40;</span>builder=<span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      to_xml<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> builder<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>xml<span style="color:#006600; font-weight:bold;">|</span>
        children.<span style="color:#9900CC;">each</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>child<span style="color:#006600; font-weight:bold;">|</span> child.<span style="color:#9900CC;">deep_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span>xml<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Child <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
    belongs_to <span style="color:#ff3333; font-weight:bold;">:parent</span>
    has_one <span style="color:#ff3333; font-weight:bold;">:grandchild</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> deep_xml<span style="color:#006600; font-weight:bold;">&#40;</span>builder=<span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      to_xml<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> builder, <span style="color:#ff3333; font-weight:bold;">:skip_instruct</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>xml<span style="color:#006600; font-weight:bold;">|</span>
        grandchild.<span style="color:#9900CC;">to_xml</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:builder</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> xml, <span style="color:#ff3333; font-weight:bold;">:skip_instruct</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Grandchild <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
    belongs_to <span style="color:#ff3333; font-weight:bold;">:child</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Now the call is simple:</span>
Parent.<span style="color:#9900CC;">firstdeep_xml</span> <span style="color:#008000; font-style:italic;">#=&gt; custom xml for a parent that includes its </span>
                        <span style="color:#008000; font-style:italic;">#   children and their grandchildren (1 each in this case)</span></pre></div></div>

<p>There&#8217;s not much to it, but I found this solution to be nice shorthand that cleaned up ugly nested to_xml blocks I was writing over and over.  I call my_record.deep_xml from any layer of the family tree and return a nice drill down of data to the leaf children.  It&#8217;s great if you&#8217;re working with a complicated database and need to be able to present your data in xml.</p>
<h3>If you are so inclined&#8230;</h3>
<p>If you really need to, you can just overwrite the to_xml method in the model.  While fine to do if you know you&#8217;ll always want that one specific template, I avoid it as much as possible and won&#8217;t cover it since examples are all over the blogosphere.  Why not just make a separate function to avoid producing unexpected results for someone else who joins your project later on?</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://blog.smartlogicsolutions.com/2008/10/10/making-willpaginate-and-rails-to_xml-play-nice-with-activeresource/" rel="bookmark" class="crp_title">Making WillPaginate and Rails to_xml play nice with ActiveResource</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/06/11/multithreading-in-ruby-on-rails/" rel="bookmark" class="crp_title">Multithreading in Ruby on Rails</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/10/28/faking-a-will-paginate-collection-on-an-active-resource-model/" rel="bookmark" class="crp_title">Faking a Will Paginate Collection on an Active Resource model</a></li><li><a href="http://blog.smartlogicsolutions.com/2009/02/24/rails-23-nested-object-forms-im-not-crazy-about-them/" rel="bookmark" class="crp_title">Rails 2.3 Nested Object Forms: I&#8217;m not Crazy about Them</a></li><li><a href="http://blog.smartlogicsolutions.com/2008/07/10/merging-a-has_many-relationship-into-one-instance/" rel="bookmark" class="crp_title">Merging a :has_many relationship into one instance</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/contextual-related-posts/">Contextual Related Posts</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://blog.smartlogicsolutions.com/2008/09/10/using-activerecords-to_xml-to-produce-custom-xml-including-deep-level-associations/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

