<?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>Rails on the Run &#187; ruby</title>
	<atom:link href="http://railsontherun.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://railsontherun.com</link>
	<description>Rails experiments by Matt Aimonetti</description>
	<lastBuildDate>Tue, 23 Feb 2010 07:28:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Ruby developers don&#8217;t scale</title>
		<link>http://railsontherun.com/2008/08/27/ruby-developers-don-t-scale/</link>
		<comments>http://railsontherun.com/2008/08/27/ruby-developers-don-t-scale/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 14:58:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[developers]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2008/08/27/ruby-developers-don-t-scale</guid>
		<description><![CDATA[Wow, it&#8217;s been a while since I blogged. With all the cool kids saying that spending time reading RSS feeds is overrated (see Defunkt&#8217;s keynote for instance) I even wonder if people will ever read this post! Anyways, I have been quite busy preparing courses for classes I gave to a bunch a great Engineers [...]]]></description>
			<content:encoded><![CDATA[<p>Wow, it&#8217;s been a while since I blogged. With all the cool kids saying that spending time reading RSS feeds is overrated (see <a href="http://rubyhoedown2008.confreaks.com/08-chris-wanstrath-keynote.html">Defunkt&#8217;s keynote</a> for instance) I even wonder if people will ever read this post!</p>
<p>Anyways, I have been quite busy preparing courses for classes I gave to a bunch a great Engineers at one of the Fortune 100 companies based in San Diego. I was also planning my big vacation trip to Europe and wrapping up few projects.</p>
<p>However, during my exile overseas, I came to the conclusion that <strong>Rubyists don&#8217;t scale</strong>. Since Twitter became stable again, we don&#8217;t hear many people ranting about Rails not scaling anymore.  With one of my clients&#8217; app handling around <strong>7 million requests/day</strong> I can tell you <strong>Ruby/Merb do scale quite well</strong>! But ruby developers don&#8217;t seem to scale for some reason.</p>
<p>Maybe saying that we(Rubyists) don&#8217;t scale isn&#8217;t technically correct but that&#8217;s basically what one of my client told me.</p>
<p>Let&#8217;s go back in time a little bit and follow my client who we will call clientX. </p>
<ul>
<li>ClientX has a <strong>great concept</strong> and wants to conquer the internet.</li>
<li>ClientX hears that <strong>Rails is the way to go</strong>.</li>
<li>ClientX hires a contractor/mercenary/freelancer/guns for hire/<strong>consultant</strong> (aka Me)</li>
<li>
<p>Me builds a <strong>killer app</strong> using <strong>Merb</strong> (killing framework)</p>
</li>
<li>
<p>ClientX raises loads of <strong>$$$</strong></p>
</li>
<li>
<p>ClientX <strong>wants to hire a team</strong> because Me doesn&#8217;t want to become a FTE</p>
</li>
<li>ClientX and Me <strong>look for Rubyists</strong> wanting to relocate and get a decent salary</li>
<li>
<p>ClientX <em>*can&#8217;t find someone</em> they consider good enough and who would accept their package</p>
</li>
<li>
<p>Many <strong>JAVA guys are available</strong> on location and accept lower packages</p>
</li>
<li><strong>Ruby app gets ported over to JAVA</strong></li>
<li><strong>Me sad</strong> <img src='http://railsontherun.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </li>
</ul>
<p>So is it really the Rubyists&#8217; fault if we don&#8217;t want to relocate and only accept higher packages? Should I blame <a href="http://blog.obiefernandez.com/">Obie</a> for telling people to charge more and teaching how to <a href="http://rubyhoedown2008.confreaks.com/07-obie-fernandez-do-the-hustle.html">hustle</a>? Or should we just tell clients that it&#8217;s time to get used to working remotely?</p>
<p>Honestly, I don&#8217;t think any of the above explanations are valid. Ruby is the new/hot technology and very few people have the skills and experience to lead major projects. These people make a good living and enjoy their &#8220;freedom&#8221; and dream of building their own products. Most of them/us value their work environment, family and are reluctant to move.</p>
<p><img src="http://img.skitch.com/20080827-rwca7tfprhce6hw19uytfqx1bc.jpg" alt="scale"/></p>
<p>At the same time, companies do need people locally(at least a core team) and can&#8217;t always afford the cool kids. </p>
<p>ClientX, quite frustrated by the whole hiring process told me once: <strong>&#8220;you Ruby folks are too unavailable and difficult to work with! We need a committed team that actually cares about the company/product.&#8221;</strong></p>
<p>That hurts when you worked hard on a project and just can&#8217;t satisfy the client by finding guys willing to relocate and work for them. <strong>It gets even more painful when your code gets entirely ported over to JAVA!</strong></p>
<p>But at the same time I understand ClientX&#8217;s motivation, PHP guys are cheaper, JAVA guys are more available, why in the word did we go with Ruby and are now struggling finding people?</p>
<p>Once again, there is positive and negative side in everything, by choosing Ruby and a &#8220;great contractor&#8221; ClientX was able to <strong>catch up with the competition and even pass them in no time</strong>. They quickly raised good money and got everything they needed to become #1. I don&#8217;t believe it would have been possible to do the same thing so quickly with JAVA for instance. However choosing a cutting edge technology means you need to look harder for talented people.</p>
<p>It&#8217;s too bad the code gets rewritten in a different language but at the same time, I do my best to facilitate the process and to keep a good relation with my client. There was nothing personal in the decision, it&#8217;s just too bad we were not able to keep on using the latest/coolest/awesomess technology available <img src='http://railsontherun.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>To finish on a positive note, here is the solution to scale your Ruby task force provided to you by the #caboose wisdom:</h2>
<p>Based on my conversations with other #caboosers who hire other devs, the word in the street is that you just need to get one or two great ruby guys (who will probably cost you a lot) and find a bunch of smart people to train. You&#8217;ll end up with an awesome team of scalable rubyists <img src='http://railsontherun.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2008/08/27/ruby-developers-don-t-scale/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>About Metaprogramming speed</title>
		<link>http://railsontherun.com/2008/06/18/about-metaprogramming-speed/</link>
		<comments>http://railsontherun.com/2008/06/18/about-metaprogramming-speed/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 07:03:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[metaprogramming]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2008/06/18/about-metaprogramming-speed</guid>
		<description><![CDATA[In a previous article I took an example of bad metaprogramming and I pushed people to think twice before using metaprogramming. My main points were that: you might make your code way slower if you don&#8217;t know what you are doing readability might drop considerably maintainability can become an issue People left some very good [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://railsontherun.com/2008/5/4/avoid-using-metaprogramming">previous article</a> I took an example of bad metaprogramming and I pushed people to think twice before using metaprogramming.</p>
<p>My main points were that:</p>
<ul>
<li>you might make your code way slower if you don&#8217;t know what you are doing</li>
<li>readability might drop considerably</li>
<li>maintainability can become an issue</li>
</ul>
<p>People left some very good comments about how to write the same module using metaprogramming and keep things fast.</p>
<p>Today <a href="http://yehudakatz.com">Wycats</a> pinged me about this post and told me that the issue was define<em>method and that class</em>eval is effectively the same as regular code, it gets evaluated in eval.c, just like regular Ruby code. On the other hand, defined_method has to marshall the proc.</p>
<p>I cleaned up my benchmarks using <a href="http://github.com/somebee/rbench/tree/master">rbench</a>, added some of the solutions provided to me and obtained the following results:</p>
<p><img src="http://img.skitch.com/20080618-ju8hy1b1pw8c3hb882ksr3hbed.jpg" alt="results"/></p>
<p>Here is the original/bad metaprogramming example:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><tt>
</tt>  <span class="r">module</span> <span class="cl">MetaTimeDSL</span><tt>
</tt><tt>
</tt>    {<span class="sy">:second</span> =&gt; <span class="i">1</span>, <tt>
</tt>     <span class="sy">:minute</span> =&gt; <span class="i">60</span>, <tt>
</tt>     <span class="sy">:hour</span> =&gt; <span class="i">3600</span>, <tt>
</tt>     <span class="sy">:day</span> =&gt; [<span class="i">24</span>,<span class="sy">:hours</span>], <tt>
</tt>     <span class="sy">:week</span> =&gt; [<span class="i">7</span>,<span class="sy">:days</span>], <tt>
</tt>     <span class="sy">:month</span> =&gt; [<span class="i">30</span>,<span class="sy">:days</span>], <tt>
</tt>     <span class="sy">:year</span> =&gt; [<span class="fl">364.25</span>, <span class="sy">:days</span>]}.each <span class="r">do</span> |meth, amount|<tt>
</tt>      define_method <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>        amount = amount.is_a?(<span class="co">Array</span>) ? amount[<span class="i">0</span>].send(amount[<span class="i">1</span>]) : amount<tt>
</tt>        <span class="pc">self</span> * amount<tt>
</tt>      <span class="r">end</span><tt>
</tt>      alias_method <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k">s</span><span class="dl">&quot;</span></span>.intern, <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="dl">&quot;</span></span><tt>
</tt>    <span class="r">end</span><tt>
</tt><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <span class="co">Numeric</span>.send <span class="sy">:include</span>, <span class="co">MetaTimeDSL</span><tt>
</tt></pre>
</td>
</tr>
</table>
<p>The no metaprogramming module is available <a href="http://pastie.textmate.org/217046">there</a></p>
<p>Refactored:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><tt>
</tt>  <span class="r">module</span> <span class="cl">RefaMetaTimeDSL</span><tt>
</tt><tt>
</tt>  {<span class="sy">:second</span> =&gt; <span class="i">1</span>, <tt>
</tt>   <span class="sy">:minute</span> =&gt; <span class="i">60</span>, <tt>
</tt>   <span class="sy">:hour</span> =&gt; <span class="i">3600</span>, <tt>
</tt>   <span class="sy">:day</span> =&gt; [<span class="i">24</span>,<span class="sy">:hours</span>], <tt>
</tt>   <span class="sy">:week</span> =&gt; [<span class="i">7</span>,<span class="sy">:days</span>], <tt>
</tt>   <span class="sy">:month</span> =&gt; [<span class="i">30</span>,<span class="sy">:days</span>], <tt>
</tt>   <span class="sy">:year</span> =&gt; [<span class="fl">364.25</span>, <span class="sy">:days</span>]}.each <span class="r">do</span> |meth, amount|<tt>
</tt>    <span class="pc">self</span>.class_eval <span class="s"><span class="dl">&lt;&lt;-RUBY</span></span><span class="s"><span class="k"><tt>
</tt>      def r_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k"><tt>
</tt>        </span><span class="il"><span class="dl">#{</span>amount.is_a?(<span class="co">Array</span>) ? <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>amount[<span class="i">0</span>]<span class="dl">}</span></span><span class="k">.</span><span class="il"><span class="dl">#{</span>amount[<span class="i">1</span>]<span class="dl">}</span></span><span class="dl">&quot;</span></span> : <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>amount<span class="dl">}</span></span><span class="dl">&quot;</span></span><span class="dl">}</span></span><span class="k"><tt>
</tt>      end<tt>
</tt>      alias_method :r_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k">s, :r_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="dl"><tt>
</tt>    RUBY</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt><tt>
</tt><span class="r">end</span><tt>
</tt><span class="co">Numeric</span>.send <span class="sy">:include</span>, <span class="co">RefaMetaTimeDSL</span><tt>
</tt></pre>
</td>
</tr>
</table>
<p>the refactor 2 or eval based solution provided by <a href="http://pastie.caboo.se/191414">Matt Jones</a> which uses class_eval like the previous refactor.</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><tt>
</tt>  <span class="r">module</span> <span class="cl">EvalMetaTimeDSL</span><tt>
</tt>    <span class="r">def</span> <span class="pc">self</span>.included(base)<tt>
</tt>      base.class_eval <span class="r">do</span><tt>
</tt>        [ [<span class="sy">:e_second</span>, <span class="i">1</span>], <tt>
</tt>          [<span class="sy">:e_minute</span>, <span class="i">60</span>], <tt>
</tt>          [<span class="sy">:e_hour</span>, <span class="i">3600</span>], <tt>
</tt>          [<span class="sy">:e_day</span>, [<span class="i">24</span>,<span class="sy">:e_hours</span>]], <tt>
</tt>          [<span class="sy">:e_week</span>, [<span class="i">7</span>,<span class="sy">:e_days</span>]], <tt>
</tt>          [<span class="sy">:e_month</span>, [<span class="i">30</span>,<span class="sy">:e_days</span>]], <tt>
</tt>          [<span class="sy">:e_year</span>, [<span class="fl">365.25</span>, <span class="sy">:e_days</span>]]].each <span class="r">do</span> |meth, amount|<tt>
</tt>            amount = amount.is_a?(<span class="co">Array</span>) ? amount[<span class="i">0</span>].send(amount[<span class="i">1</span>]) : amount<tt>
</tt>            eval <span class="s"><span class="dl">&quot;</span><span class="k">def </span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k">; self*</span><span class="il"><span class="dl">#{</span>amount<span class="dl">}</span></span><span class="k">; end</span><span class="dl">&quot;</span></span><tt>
</tt>            alias_method <span class="s"><span class="dl">&quot;</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k">s</span><span class="dl">&quot;</span></span>, meth<tt>
</tt>          <span class="r">end</span><tt>
</tt>      <span class="r">end</span><tt>
</tt>    <span class="r">end</span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <span class="co">Numeric</span>.send <span class="sy">:include</span>, <span class="co">EvalMetaTimeDSL</span><tt>
</tt></pre>
</td>
</tr>
</table>
<p>and finally, the &#8220;better metaprogramming&#8221; version:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><tt>
</tt> <span class="r">module</span> <span class="cl">GoodMetaTimeDSL</span><tt>
</tt><tt>
</tt>  <span class="co">SECOND</span>  = <span class="i">1</span><tt>
</tt>  <span class="co">MINUTE</span>  = <span class="co">SECOND</span> * <span class="i">60</span><tt>
</tt>  <span class="co">HOUR</span>    = <span class="co">MINUTE</span> * <span class="i">60</span><tt>
</tt>  <span class="co">DAY</span>     = <span class="co">HOUR</span> * <span class="i">24</span><tt>
</tt>  <span class="co">WEEK</span>    = <span class="co">DAY</span> * <span class="i">7</span><tt>
</tt>  <span class="co">MONTH</span>   = <span class="co">DAY</span> * <span class="i">30</span><tt>
</tt>  <span class="co">YEAR</span>    = <span class="co">DAY</span> * <span class="fl">364.25</span><tt>
</tt>  <tt>
</tt>  <span class="s"><span class="dl">%w[</span><span class="k">SECOND MINUTE HOUR DAY WEEK MONTH YEAR</span><span class="dl">]</span></span>.each <span class="r">do</span> |const_name|<tt>
</tt>      meth = const_name.downcase<tt>
</tt>      class_eval <span class="s"><span class="dl">&lt;&lt;-RUBY</span></span> <span class="s"><span class="k"><tt>
</tt>        def g_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k"> <tt>
</tt>          self * </span><span class="il"><span class="dl">#{</span>const_name<span class="dl">}</span></span><span class="k"> <tt>
</tt>        end <tt>
</tt>        alias g_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k">s g_</span><span class="il"><span class="dl">#{</span>meth<span class="dl">}</span></span><span class="k"> </span><span class="dl"><tt>
</tt>      RUBY</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><span class="co">Numeric</span>.send <span class="sy">:include</span>, <span class="co">GoodMetaTimeDSL</span><tt>
</tt></pre>
</td>
</tr>
</table>
<p>Looking at the refactored version by Wycats, you can see he&#8217;s right and the major issue with the original version was define<em>method. Using class</em>eval does make things almost as fast and even faster than the no metaprogramming version.</p>
<p>Interesting enough, the benchmarks show that some methods from the meta modules are faster than the ones from the no meta module. Overall, an optimized metaprogramming can be more or else as fast as a non meta code. Of course, with the new VMs coming up, things might change a little bit depending on the language implementation.</p>
<p><em>In conclusion, metaprogramming can be as fast as no metaprogramming but that won&#8217;t help your code readability and maintainability, so make sure to only use this great trick when needed!</em></p>
<p>p.s: <a href="http://pastie.textmate.org/217071">here</a> is the benchmark file if you don&#8217;t believe me <img src='http://railsontherun.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2008/06/18/about-metaprogramming-speed/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>News update</title>
		<link>http://railsontherun.com/2008/06/18/news-update/</link>
		<comments>http://railsontherun.com/2008/06/18/news-update/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 01:40:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[conf]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2008/06/18/news-update</guid>
		<description><![CDATA[I realized I haven&#8217;t updated this blog in a while. Here is a quick update on what&#8217;s happened and on things to come: RailsConf 08. Great conference, probably my last Rails Conf though. I&#8217;ll be in Orlando for Ruby Conf 08 and I&#8217;ll focus on 1 or 2 local conferences (probably mountain west and another [...]]]></description>
			<content:encoded><![CDATA[<p>I realized I haven&#8217;t updated this blog in a while. Here is a quick update on what&#8217;s happened and on things to come:</p>
<ul>
<li>
<p><a href="http://en.oreilly.com/rails2008/public/content/home">RailsConf 08</a>. Great conference, probably my last Rails Conf though. I&#8217;ll be in Orlando for <a href="http://rubyconf.org/">Ruby Conf 08</a> and I&#8217;ll focus on 1 or 2 local conferences (probably <a href="http://mtnwestrubyconf.org/">mountain west</a> and another one).</p>
</li>
<li>
<p>MerbCamp 08 in San Diego this Fall organized by <a href="http://sdruby.com">SD Ruby</a>. Details are not finalized yet but <a href="http://yehudakatz.com/">Yehuda Katz</a> announced it during his Merb talk at RailsConf.</p>
</li>
<li>
<p>Moved this blog to a new <a href="http://joyent.com">Joyent accelerator</a> with git support and finally have the possibility to use Ambition! (planning on moving from Mephisto to <a href="http://crazycool.co.uk/2008/04/26/announcing-feather">Feather</a>)</p>
</li>
<li>
<p>Launched a client&#8217;s Merb app and getting around 3 million hits/day. Merb is just awesome. (more info when the client&#8217;s app gets out of beta)</p>
</li>
<li>
<p>I&#8217;ll join <a href="http://railsenvy.com/">Gregg Pollack</a> from <a href="http://railsenvy.com/">http://railsenvy.com/</a> during <a href="http://qcon.infoq.com">Qcon</a> and take part in the <a href="http://qcon.infoq.com/sanfrancisco-2008/tracks/show_track.jsp?trackOID=172">Ruby for the Enterprise</a> track. <a href="http://qcon.infoq.com/sanfrancisco-2008/speaker/Matt+Aimonetti">My talk</a> will focus on Merb usage in real life.</p>
</li>
<li>
<p>Renamed my github username, new repo url: <a href="http://github.com/mattetti">http://github.com/mattetti</a> (sorry about that)</p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2008/06/18/news-update/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>a new useless Gem</title>
		<link>http://railsontherun.com/2007/12/04/a-new-useless-gem/</link>
		<comments>http://railsontherun.com/2007/12/04/a-new-useless-gem/#comments</comments>
		<pubDate>Tue, 04 Dec 2007 08:28:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[activation code]]></category>
		<category><![CDATA[DrNic]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[generator]]></category>
		<category><![CDATA[lorem ipsum]]></category>
		<category><![CDATA[newgem]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sqlite3]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2007/12/04/a-new-useless-gem</guid>
		<description><![CDATA[During Thanksgiving break I had fun with a friend of mine working on a Ruby challenge while digesting the traditional turkey.]]></description>
			<content:encoded><![CDATA[<p>During Thanksgiving break I had fun with a friend of mine working on a Ruby challenge while digesting the traditional turkey.</p>
<p><img src="http://content.screencast.com/media/a088950c-c9d1-4655-9b6e-b917e04dd6ec_74569570-772f-4886-b2ea-f305d1ede3aa_static_0_0_00000026.png" alt="http://content.screencast.com/media/a088950c-c9d1-4655-9b6e-b917e04dd6ec<em>74569570-772f-4886-b2ea-f305d1ede3aa</em>static<em>0</em>0_00000026.png&#8221;/></p>
<p>The challenge was quite simple, create a small library that can generate random words from the English dictionary. </p>
<p>But of course there was a twist. One should be able to choose the total amount of characters, the amount of words and the separator between the words. However we both had a <a href="http://wordlist.sourceforge.net/">word list</a>.</p>
<p>I personally decided to use <a href="http://www.sqlite.org/">SQlite3</a> to store the words after parsing the text file if the database is empty.</p>
<p>It was a good exercise and it got me to play with SQLite and one of the <a href="http://rubyforge.org/projects/sqlite-ruby/">Ruby adapter library</a>. Once I was done, I decide to play with <a href="http://drnicwilliams.com/">DrNic</a> cool <a href="http://newgem.rubyforge.org/">Gem generator</a>.</p>
<p><img src="http://static.flickr.com/50/130749539_89959dd059_t.jpg" alt="http://static.flickr.com/50/130749539<em>89959dd059</em>t.jpg&#8221;/> </p>
<p>Nic is my favorite Aussie&#8217;s Rubyist (ok, I don&#8217;t know many) and I&#8217;ve been wanting to check on this lib for a very long time. And I have to say he did an awesome job! Writing a Ruby Gem has never that easy! And on top of that the generator creates RSpec examples (or test/unit tests), a basic website for your gem and has a bunch of rake tasks to deploy your newly created gem.</p>
<p>Feel free to check the source code:</p>
<p><a href="http://random-word-gen.rubyforge.org/svn/">http://random-word-gen.rubyforge.org/svn/</a></p>
<p><a href="http://rubyforge.org/projects/random-word-gen/">And the Rubyforge site</a></p>
<p>By the way, I did find an almost useful use for this gem. Activation code generator. You know, the kind of string your receive on by email or SMS to activate a feature or an account. It&#8217;s always a pain to type a MD5Hash string, while, when using the word generator, the string is made of existing words, making the process way more user friendly.</p>
<p>I also plan on adding some random copyleft text to the sqlite db so the Gem will be able to generate titles, paragraphs and random quotes. I&#8217;m just tired of reading <a href="http://en.wikipedia.org/wiki/Lorem_ipsum">lorem ipsum</a> and on top of that, I get to it, I might had text in various languages so you check if your app breaks when using another char set, or if your layout can&#8217;t handle too much text.   </p>
<p>Honestly, I don&#8217;t expect you to use this gem, but I jut wanted to encourage people to start writing their own gem, the process is super easy and rewarding. And actually, feel free to try the challenge and post a link to your implementation in the comments. (That&#8217;s seriously, the best way to learn)</p>
<p>p.s: I&#8217;m sorry about my RSS feed constantly being reset, it seems to be a problem with Mephisto, my blog engine and we are trying to figure out what&#8217;s going on.</p>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2007/12/04/a-new-useless-gem/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to test a XML builder view</title>
		<link>http://railsontherun.com/2007/10/31/how-to-test-a-xml-builder-view/</link>
		<comments>http://railsontherun.com/2007/10/31/how-to-test-a-xml-builder-view/#comments</comments>
		<pubDate>Wed, 31 Oct 2007 08:32:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[BDD]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[xml builder]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2007/10/31/how-to-test-a-xml-builder-view</guid>
		<description><![CDATA[As a good Rubyist, I do TDD and even BDD. Since I&#8217;ve started using RSpec I&#8217;ve started writing tests against my views. RSpec makes things really easy and I&#8217;ve been enjoying testing my views. I&#8217;m not the only one having fun, check this great post from Mr Planet Argon aka Robby Russel Recently I was [...]]]></description>
			<content:encoded><![CDATA[<p>As a good Rubyist, I do <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> and even <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">BDD</a>. </p>
<p>Since I&#8217;ve started using <a href="http://rspec.rubyforge.org/">RSpec</a> I&#8217;ve started writing tests against my views. RSpec makes things really easy and I&#8217;ve been enjoying testing my views.</p>
<p>I&#8217;m not the only one having fun, check <a href="http://www.robbyonrails.com/articles/2007/08/02/spec-your-views">this great post</a> from Mr <a href="http://www.planetargon.com/">Planet Argon</a> aka <a href="http://www.robbyonrails.com">Robby Russel</a></p>
<p>Recently I was working on implementing some <a href="http://railsontherun.com/2007/10/4/sexy-charts-in-less-than-5-minutes">Sexy Charts</a> and I was using a XML builder to create an XML view of for a controller. Since I wanted to be a good Rails Ninja and obey the BDD rules, I figured I needed to test my XML view. Making sure that the nodes and the attributes were properly created. Turned out that is wasn&#8217;t too hard, there was many options but none were very well documented so I decided to write this quick tutorial.</p>
<h2>UPDATE 31 Oct 2007: After a comment from <a href="http://joshknowles.com">Josh Knowles</a>, I updated the tests to test with have_tags (built in RSpec) and hpricot.</h2>
<h2>Hpricot</h2>
<p><a href="http://code.whytheluckystiff.net/hpricot/">hpricot</a> is a awesome HTML parser perfect for <a href="http://en.wikipedia.org/wiki/Screen_scraping">screen scraping</a>. But wait, there&#8217;s more to this awesome library, <a href="http://code.whytheluckystiff.net/hpricot/wiki/HpricotXML">hpricot can also parse XML</a>.</p>
<p>If you watched the excellent <a href="http://peepcode.com/products">RSpec peepcasts</a> you probably noticed that <a href="http://topfunky.com/">topfunky</a> aka <a href="http://geoffreygrosenbach.com/">Geoffrey Grosenbach</a> uses hpricot to test a remote API.</p>
<p>In our case, we&#8217;ll use hpricot to test that our generated XML follows our expectations.</p>
<h2>XML Builder + RSpec</h2>
<p>Let&#8217;s write a quick test to make sure our controller uses a XML builder view:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  describe <span class="co">AveragesController</span>, <span class="s"><span class="dl">&quot;</span><span class="k">handling GET /averages.xml</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt><tt>
</tt>    before <span class="r">do</span><tt>
</tt>      <span class="co">Average</span>.stub!(<span class="sy">:find</span>).and_return(<span class="iv">@average</span>)<tt>
</tt>    <span class="r">end</span><tt>
</tt>  <tt>
</tt>    <span class="r">def</span> <span class="fu">do_get</span><tt>
</tt>      <span class="iv">@request</span>.env[<span class="s"><span class="dl">&quot;</span><span class="k">HTTP_ACCEPT</span><span class="dl">&quot;</span></span>] = <span class="s"><span class="dl">&quot;</span><span class="k">application/xml</span><span class="dl">&quot;</span></span><tt>
</tt>      get <span class="sy">:index</span><tt>
</tt>    <span class="r">end</span><tt>
</tt>  <tt>
</tt>    it <span class="s"><span class="dl">&quot;</span><span class="k">should render the action using the XML builder</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>      do_get<tt>
</tt>      response.should render_template(<span class="s"><span class="dl">'</span><span class="k">averages/index.xml.builder</span><span class="dl">'</span></span>)<tt>
</tt>    <span class="r">end</span><tt>
</tt><tt>
</tt>  <span class="r">end</span></pre>
</td>
</tr>
</table>
<p>To make this example pass, we need to modify our rspec generated controller.</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  <span class="r">def</span> <span class="fu">index</span><tt>
</tt>    <span class="iv">@averages</span> = <span class="co">Average</span>.find(<span class="sy">:all</span>)<tt>
</tt>  <tt>
</tt>    respond_to <span class="r">do</span> |format|<tt>
</tt>      format.html <span class="c"># index.html.erb</span><tt>
</tt>      format.xml  { render <span class="sy">:action</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">index.xml.builder</span><span class="dl">&quot;</span></span>, <span class="sy">:layout</span> =&gt; <span class="pc">false</span> }<tt>
</tt>    <span class="r">end</span><tt>
</tt>  <span class="r">end</span></pre>
</td>
</tr>
</table>
<p>(Please note that I&#8217;m using Rails 2.0 and that&#8217;s why I&#8217;m not using a .rxml view)</p>
<p>Here is what our XML file should end up looking like:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt><strong>25</strong><tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt><strong>35</strong><tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt>39<tt>
</tt><strong>40</strong><tt>
</tt>41<tt>
</tt>42<tt>
</tt>43<tt>
</tt>44<tt>
</tt><strong>45</strong><tt>
</tt>46<tt>
</tt>47<tt>
</tt>48<tt>
</tt>49<tt>
</tt><strong>50</strong><tt>
</tt>51<tt>
</tt>52<tt>
</tt>53<tt>
</tt>54<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  &lt;<span class="i">?x</span>ml version=<span class="s"><span class="dl">&quot;</span><span class="k">1.0</span><span class="dl">&quot;</span></span> encoding=<span class="s"><span class="dl">&quot;</span><span class="k">UTF-8</span><span class="dl">&quot;</span></span>?&gt;<tt>
</tt>  &lt;chart&gt;<tt>
</tt>    &lt;series&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">0</span><span class="dl">&quot;</span></span>&gt;<span class="co">January</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>      &lt;value xid=&quot;1&quot;&gt;February&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">2</span><span class="dl">&quot;</span></span>&gt;<span class="co">March</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>      &lt;value xid=&quot;3&quot;&gt;April&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">4</span><span class="dl">&quot;</span></span>&gt;<span class="co">May</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt><tt>
</tt>      &lt;value xid=&quot;5&quot;&gt;June&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">6</span><span class="dl">&quot;</span></span>&gt;<span class="co">July</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>      &lt;value xid=&quot;7&quot;&gt;August&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">8</span><span class="dl">&quot;</span></span>&gt;<span class="co">September</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>      &lt;value xid=&quot;9&quot;&gt;October&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">10</span><span class="dl">&quot;</span></span>&gt;<span class="co">November</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt><tt>
</tt>      &lt;value xid=&quot;11&quot;&gt;December&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>    &lt;<span class="rx"><span class="dl">/</span><span class="k">series&gt;<tt>
</tt>    &lt;graphs&gt;<tt>
</tt>      &lt;graph fill_alpha=&quot;50&quot; color=&quot;#FF0000&quot; fill_color=&quot;#CC0000&quot; title=&quot;high&quot;&gt;<tt>
</tt>        &lt;value xid=&quot;0&quot;&gt;65.1&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">1</span><span class="dl">&quot;</span></span>&gt;<span class="fl">65.7</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;2&quot;&gt;64.9&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt><tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">3</span><span class="dl">&quot;</span></span>&gt;<span class="fl">66.7</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;4&quot;&gt;67.1&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">5</span><span class="dl">&quot;</span></span>&gt;<span class="fl">69.3</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;6&quot;&gt;73.0&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">7</span><span class="dl">&quot;</span></span>&gt;<span class="fl">74.8</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;8&quot;&gt;75.4&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt><tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">9</span><span class="dl">&quot;</span></span>&gt;<span class="fl">73.4</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;10&quot;&gt;68.9&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">11</span><span class="dl">&quot;</span></span>&gt;<span class="fl">65.3</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>      &lt;</span><span class="dl">/</span></span>graph&gt;<tt>
</tt>      &lt;graph fill_alpha=<span class="s"><span class="dl">&quot;</span><span class="k">50</span><span class="dl">&quot;</span></span> color=<span class="s"><span class="dl">&quot;</span><span class="k">#0000CC</span><span class="dl">&quot;</span></span> fill_color=<span class="s"><span class="dl">&quot;</span><span class="k">#0000CC</span><span class="dl">&quot;</span></span> title=<span class="s"><span class="dl">&quot;</span><span class="k">low</span><span class="dl">&quot;</span></span>&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">0</span><span class="dl">&quot;</span></span>&gt;<span class="fl">48.9</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;1&quot;&gt;50.7&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt><tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">2</span><span class="dl">&quot;</span></span>&gt;<span class="fl">52.9</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;3&quot;&gt;55.6&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">4</span><span class="dl">&quot;</span></span>&gt;<span class="fl">59.2</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;5&quot;&gt;61.9&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">6</span><span class="dl">&quot;</span></span>&gt;<span class="fl">65.7</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;7&quot;&gt;67.3&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt><tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">8</span><span class="dl">&quot;</span></span>&gt;<span class="fl">65.7</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;9&quot;&gt;61.0&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>        &lt;value xid=<span class="s"><span class="dl">&quot;</span><span class="k">10</span><span class="dl">&quot;</span></span>&gt;<span class="fl">54.0</span>&lt;<span class="rx"><span class="dl">/</span><span class="k">value&gt;<tt>
</tt>        &lt;value xid=&quot;11&quot;&gt;48.7&lt;</span><span class="dl">/</span></span>value&gt;<tt>
</tt>      &lt;<span class="rx"><span class="dl">/</span><span class="k">graph&gt;<tt>
</tt>    &lt;</span><span class="dl">/</span></span>graphs&gt;<tt>
</tt>  &lt;<span class="rx"><span class="dl">/</span><span class="k">chart&gt;<tt>
</tt>  </span></span></pre>
</td>
</tr>
</table>
<p>Let&#8217;s write some tests to make sure our view is ok:</p>
<p>index.xml.builder_spec.rb</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt><strong>25</strong><tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt><strong>35</strong><tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt>39<tt>
</tt><strong>40</strong><tt>
</tt>41<tt>
</tt>42<tt>
</tt>43<tt>
</tt>44<tt>
</tt><strong>45</strong><tt>
</tt>46<tt>
</tt>47<tt>
</tt>48<tt>
</tt>49<tt>
</tt><strong>50</strong><tt>
</tt>51<tt>
</tt>52<tt>
</tt>53<tt>
</tt>54<tt>
</tt><strong>55</strong><tt>
</tt>56<tt>
</tt>57<tt>
</tt>58<tt>
</tt>59<tt>
</tt><strong>60</strong><tt>
</tt>61<tt>
</tt>62<tt>
</tt>63<tt>
</tt>64<tt>
</tt><strong>65</strong><tt>
</tt>66<tt>
</tt>67<tt>
</tt>68<tt>
</tt>69<tt>
</tt><strong>70</strong><tt>
</tt>71<tt>
</tt>72<tt>
</tt>73<tt>
</tt>74<tt>
</tt><strong>75</strong><tt>
</tt>76<tt>
</tt>77<tt>
</tt>78<tt>
</tt>79<tt>
</tt><strong>80</strong><tt>
</tt>81<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="co">File</span>.dirname(<span class="pc">__FILE__</span>) + <span class="s"><span class="dl">'</span><span class="k">/../../spec_helper</span><span class="dl">'</span></span><tt>
</tt>require <span class="s"><span class="dl">'</span><span class="k">hpricot</span><span class="dl">'</span></span><tt>
</tt><tt>
</tt>describe <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>  include <span class="co">AveragesHelper</span><tt>
</tt>  <tt>
</tt>  before <span class="r">do</span><tt>
</tt>    average_1 = mock_model(<span class="co">Average</span>)<tt>
</tt>    average_1.stub!(<span class="sy">:month</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">January</span><span class="dl">&quot;</span></span>)<tt>
</tt>    average_1.stub!(<span class="sy">:high</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">74.5</span><span class="dl">&quot;</span></span>)<tt>
</tt>    average_1.stub!(<span class="sy">:low</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">61.5</span><span class="dl">&quot;</span></span>)<tt>
</tt>    average_2 = mock_model(<span class="co">Average</span>)<tt>
</tt>    average_2.stub!(<span class="sy">:month</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">February</span><span class="dl">&quot;</span></span>)<tt>
</tt>    average_2.stub!(<span class="sy">:high</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">82.5</span><span class="dl">&quot;</span></span>)<tt>
</tt>    average_2.stub!(<span class="sy">:low</span>).and_return(<span class="s"><span class="dl">&quot;</span><span class="k">71.5</span><span class="dl">&quot;</span></span>)<tt>
</tt><tt>
</tt>    assigns[<span class="sy">:averages</span>] = [average_1, average_2]<tt>
</tt>  <span class="r">end</span><tt>
</tt><tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should render the months in the series</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">value</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">'</span><span class="k">January</span><span class="dl">'</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">value</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">'</span><span class="k">February</span><span class="dl">'</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:value</span>).first.inner_html.should == <span class="s"><span class="dl">'</span><span class="k">January</span><span class="dl">'</span></span><tt>
</tt>    (doc/<span class="sy">:value</span>)[<span class="i">1</span>].inner_html.should == <span class="s"><span class="dl">'</span><span class="k">February</span><span class="dl">'</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should set the xid attributes for the series</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">value[xid=0]:first-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">value[xid=1]:last-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:value</span>).first[<span class="s"><span class="dl">&quot;</span><span class="k">xid</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">0</span><span class="dl">'</span></span><tt>
</tt>    (doc/<span class="sy">:value</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">xid</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">1</span><span class="dl">'</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should have 2 graphs and they should have a title</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[title=high]:first-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[title=low]:last-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>).size.should == <span class="i">2</span><tt>
</tt>    (doc/<span class="sy">:graph</span>).first[<span class="s"><span class="dl">&quot;</span><span class="k">title</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">high</span><span class="dl">'</span></span><tt>
</tt>    (doc/<span class="sy">:graph</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">title</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">low</span><span class="dl">'</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should have a color set by graph</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[color]:first-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[color]:last-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[fill_color]:last-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph[fill_alpha]:last-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>).first[<span class="s"><span class="dl">&quot;</span><span class="k">color</span><span class="dl">&quot;</span></span>].should_not be_nil<tt>
</tt>    (doc/<span class="sy">:graph</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">color</span><span class="dl">&quot;</span></span>].should_not be_nil<tt>
</tt>    (doc/<span class="sy">:graph</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">fill_color</span><span class="dl">&quot;</span></span>].should_not be_nil<tt>
</tt>    (doc/<span class="sy">:graph</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">fill_alpha</span><span class="dl">&quot;</span></span>].should_not be_nil<tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should have an xid for each graph value</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph &gt; value[xid=0]:first-child</span><span class="dl">&quot;</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>/<span class="sy">:value</span>).first[<span class="s"><span class="dl">&quot;</span><span class="k">xid</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">&quot;</span><span class="k">0</span><span class="dl">&quot;</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  it <span class="s"><span class="dl">&quot;</span><span class="k">should have the high average as values of the first graph</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    response.should have_tag(<span class="s"><span class="dl">&quot;</span><span class="k">graph &gt; value:first-child</span><span class="dl">&quot;</span></span>, <span class="s"><span class="dl">&quot;</span><span class="k">74.5</span><span class="dl">&quot;</span></span>)<tt>
</tt>    <span class="c"># Same thing but with Hpricot</span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>/<span class="sy">:value</span>).first.inner_html.should == <span class="s"><span class="dl">&quot;</span><span class="k">74.5</span><span class="dl">&quot;</span></span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt><span class="r">end</span></pre>
</td>
</tr>
</table>
<p>The first thing you must do (after installing the hpricot gem) is to require hpricot in your test:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre><tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  require <span class="s"><span class="dl">'</span><span class="k">hpricot</span><span class="dl">'</span></span></pre>
</td>
</tr>
</table>
<p>Now that hpricot is created we can use it to parse the response and check against our expectations.</p>
<p>(we create mock objects to pass to the view so we know exactly what to expect and we separate Model/Controller/Views tests)</p>
<p>To check against our response we have to use hpricot parser syntax. It might look at bit funny at first, but believe me it&#8217;s really easy once you get it.</p>
<p>But first, let&#8217;s parse the view:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># Render the mocked up data using the xml view</span><tt>
</tt>render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt><span class="c"># Load and parse the view response body:</span><tt>
</tt>doc = <span class="co">Hpricot</span>.XML(response.body.to_s)  </pre>
</td>
</tr>
</table>
<p>Let&#8217;s look at the first test:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  it <span class="s"><span class="dl">&quot;</span><span class="k">should render the months in the series</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:value</span>).first.inner_html.should == <span class="s"><span class="dl">'</span><span class="k">January</span><span class="dl">'</span></span><tt>
</tt>    (doc/<span class="sy">:value</span>)[<span class="i">1</span>].inner_html.should == <span class="s"><span class="dl">'</span><span class="k">February</span><span class="dl">'</span></span><tt>
</tt>  <span class="r">end</span></pre>
</td>
</tr>
</table>
<p>(doc/:value) returns all the value nodes, we take the first one and extract its content. We expect that it would match the name of the month for the first average.</p>
<p>Let&#8217;s now look at another test:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  it <span class="s"><span class="dl">&quot;</span><span class="k">should have 2 graphs and they should have a title</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>).size.should == <span class="i">2</span><tt>
</tt>    (doc/<span class="sy">:graph</span>).first[<span class="s"><span class="dl">&quot;</span><span class="k">title</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">high</span><span class="dl">'</span></span><tt>
</tt>    (doc/<span class="sy">:graph</span>).last[<span class="s"><span class="dl">&quot;</span><span class="k">title</span><span class="dl">&quot;</span></span>].should == <span class="s"><span class="dl">'</span><span class="k">low</span><span class="dl">'</span></span><tt>
</tt>  <span class="r">end</span></pre>
</td>
</tr>
</table>
<p>The thing to look at here is the fact that we are checking on the node&#8217;s attribute &#8220;title&#8221;. Really simple syntax and clean test, isn&#8217;t it?</p>
<p>Finally let&#8217;s look at the last example:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">  it <span class="s"><span class="dl">&quot;</span><span class="k">should have the high average as values of the first graph</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>    render <span class="s"><span class="dl">&quot;</span><span class="k">/averages/index.xml.builder</span><span class="dl">&quot;</span></span><tt>
</tt>    doc = <span class="co">Hpricot</span>.XML(response.body.to_s)<tt>
</tt>    (doc/<span class="sy">:graph</span>/<span class="sy">:value</span>).first.inner_html.should == <span class="s"><span class="dl">&quot;</span><span class="k">74.5</span><span class="dl">&quot;</span></span><tt>
</tt>  <span class="r">end</span></pre>
</td>
</tr>
</table>
<p>We are checking that the content of the first value node nested inside a graph node is equal to 74.5 which is the high average for the first month. </p>
<p>In practice, you probably won&#8217;t write all these tests at once, but anyway, let&#8217;s look at our XML builder which will make all these tests pass:</p>
<table class="CodeRay">
<tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }">
<pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt><strong>5</strong><tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt><strong>15</strong><tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt></pre>
</td>
<td class="code">
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">xml.instruct! <span class="sy"> <img src='http://railsontherun.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml</span>, <span class="sy">:version</span>=&gt;<span class="s"><span class="dl">&quot;</span><span class="k">1.0</span><span class="dl">&quot;</span></span>, <span class="sy">:encoding</span>=&gt;<span class="s"><span class="dl">&quot;</span><span class="k">UTF-8</span><span class="dl">&quot;</span></span><tt>
</tt>xml.chart <span class="r">do</span><tt>
</tt>  xml.series <span class="r">do</span>    <tt>
</tt>    <span class="iv">@averages</span>.each_with_index <span class="r">do</span> |average, index|<tt>
</tt>      xml.value average.month, <span class="sy"> <img src='http://railsontherun.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> id</span> =&gt; index<tt>
</tt>    <span class="r">end</span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt>  xml.graphs <span class="r">do</span><tt>
</tt>    xml.graph <span class="sy">:title</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">high</span><span class="dl">'</span></span>, <span class="sy">:color</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">#FF0000</span><span class="dl">&quot;</span></span>, <span class="sy">:fill_alpha</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">50</span><span class="dl">&quot;</span></span>, <span class="sy">:fill_color</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">#CC0000</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>      <span class="iv">@averages</span>.each_with_index <span class="r">do</span> |average, index|<tt>
</tt>        xml.value average.high, <span class="sy"> <img src='http://railsontherun.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> id</span> =&gt; index<tt>
</tt>      <span class="r">end</span><tt>
</tt>    <span class="r">end</span><tt>
</tt>    <tt>
</tt>    xml.graph <span class="sy">:title</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">low</span><span class="dl">'</span></span>, <span class="sy">:color</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">#0000CC</span><span class="dl">&quot;</span></span>, <span class="sy">:fill_alpha</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">50</span><span class="dl">&quot;</span></span>, <span class="sy">:fill_color</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">#0000CC</span><span class="dl">&quot;</span></span> <span class="r">do</span><tt>
</tt>      <span class="iv">@averages</span>.each_with_index <span class="r">do</span> |average, index|<tt>
</tt>        xml.value average.low, <span class="sy"> <img src='http://railsontherun.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> id</span> =&gt; index<tt>
</tt>      <span class="r">end</span><tt>
</tt>    <span class="r">end</span><tt>
</tt>  <span class="r">end</span><tt>
</tt>  <tt>
</tt><span class="r">end</span></pre>
</td>
</tr>
</table>
<p>Hpricot is a <em>really</em> nice tool which can make your BDD life much easier. And even if you don&#8217;t do BDD/TDD yet, it&#8217;s a great way to verify that any XML data you receive/generate is valid.</p>
<h2>Happy testing</h2>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2007/10/31/how-to-test-a-xml-builder-view/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Leopard &#8211; Autotest &#8211; Growl Notification</title>
		<link>http://railsontherun.com/2007/10/31/leopard-autotest/</link>
		<comments>http://railsontherun.com/2007/10/31/leopard-autotest/#comments</comments>
		<pubDate>Wed, 31 Oct 2007 00:10:00 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[autotest]]></category>
		<category><![CDATA[growl]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[zentest]]></category>

		<guid isPermaLink="false">http://railsontherun.com/2007/10/31/leopard-autotest</guid>
		<description><![CDATA[As many of you know, I&#8217;m a great RSpec and autotest fan. Last night, I upgraded my MacBook to from Tiger to Leopard and I everything went very well&#8230; apart that Autotest stopped notifying me using Growl when my tests pass or fail Growl itself works fine, even when using spaces. However growlNotify, the Growl [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm3.static.flickr.com/2176/1805711983_8d7811d890.jpg?v=0" alt="mac os X leopard"/></p>
<p>As many of you know, I&#8217;m a great <a href="http://rspec.rubyforge.org/">RSpec</a> and <a href="http://www.zenspider.com/ZSS/Products/ZenTest/">autotest</a> fan.</p>
<p>Last night, I upgraded my MacBook to from Tiger to Leopard and I everything went very well&#8230; apart that Autotest stopped notifying me using Growl when my tests pass or fail <img src='http://railsontherun.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>Growl itself works fine, even when using spaces. </p>
<p>However <em><a href="http://www.growl.info/documentation/growlnotify.php">growlNotify</a></em>, the <a href="http://www.growl.info/">Growl</a> plugin used by autotest <em>doesn&#8217;t seem to be Leopard compatible yet</em>. </p>
<p>Just thought you guys should know that before upgrading.</p>
<p><img src="http://www.growl.info/img/growlicon.png" alt="growl"/></p>
]]></content:encoded>
			<wfw:commentRss>http://railsontherun.com/2007/10/31/leopard-autotest/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

