<?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>catapult-creative.com &#187; Ruby</title>
	<atom:link href="http://www.catapult-creative.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.catapult-creative.com</link>
	<description>worldwide (web) whatnot</description>
	<lastBuildDate>Wed, 18 Aug 2010 13:33:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>When open-uri can&#8217;t convert Hash into String &#8212; another time it happens</title>
		<link>http://www.catapult-creative.com/2009/10/25/when-open-uri-cant-convert-hash-into-string-another-time-it-happens/</link>
		<comments>http://www.catapult-creative.com/2009/10/25/when-open-uri-cant-convert-hash-into-string-another-time-it-happens/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 00:20:13 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2009/10/25/when-open-uri-cant-convert-hash-into-string-another-time-it-happens/</guid>
		<description><![CDATA[Short answer: OpenURI doesn&#8217;t support the &#8220;feed://&#8221; pseudo protocol and if you try it with a hash of header options it gives you the same error as if, like some dumb muppet, you hadn&#8217;t required the library in the first place.  In other words, it falls through to Kernel#open and leaves you scratching your [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Short answer:</strong> OpenURI doesn&#8217;t support the &#8220;feed://&#8221; pseudo protocol and if you try it with a hash of header options it gives you the same error as if, like some dumb muppet, you hadn&#8217;t required the library in the first place.  In other words, it falls through to Kernel#open and leaves you scratching your head.</p>

<p><strong>Long answer:</strong> Read on, code fiends.  Read on.</p>

<p>Tonight I decided to earn some HusbandPoints&trade; by helping my wife get a large number of tagged photos off <a href="http://picasa.google.com/">Picasa</a> for a project that she&#8217;s working on.  Downloading them by hand would&#8217;ve been a pain in the ass timewise and also would&#8217;ve been a big pain opportunity-cost wise as well, since she would&#8217;ve had to take time out from the main body of the project (a homemade cookbook for a friend&#8217;s wedding) to do a dumb photo-by-photo clickfest through the entire large Picasa album she&#8217;d assembled with her friends.  Plus it gave me a reason to mess around w/ the Google <span class="caps">API</span>s some &#8212; knowledge that would almost certainly come in handy later.</p>

<p>Now, the easiest way to go about scripting this w/ Ruby involves using <strong>open-uri</strong> to pass in the authorization token from Google into every request, per their <a href="http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html">ClientLogin authentication method</a>.  You do that with a piece of code like this:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co1"># Assuming that @auth_token is set by a login method</span><br />
<span class="kw1">def</span> http_header<br />
&nbsp; <span class="br0">&#123;</span><span class="st0">&quot;Authorization&quot;</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;GoogleLogin auth=#{@auth_token}&quot;</span><span class="br0">&#125;</span><br />
<span class="kw1">end</span><br />
<br />
<span class="co1"># HTTP GET a Google content feed (Atom)</span><br />
<span class="kw1">def</span> get<span class="br0">&#40;</span>url<span class="br0">&#41;</span><br />
&nbsp; response = <span class="kw3">open</span><span class="br0">&#40;</span>url, http_header<span class="br0">&#41;</span><span class="br0">&#123;</span> <span class="sy0">|</span>f<span class="sy0">|</span> f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#125;</span><br />
&nbsp; Hpricot.<span class="me1">XML</span><span class="br0">&#40;</span>response<span class="br0">&#41;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Here we&#8217;re getting the content from Google (which will come as an Atom feed, as all of their various pieces of content do) and then parsing the result with <a href="http://github.com/whymirror/hpricot">Hpricot</a>.  We pass the <strong>http_header</strong> Hash to OpenURI&#8217;s <strong>open</strong> method to specify a set of <span class="caps">HTTP </span>header variables.  This is supposed to be easy, but tonight it wasn&#8217;t, and my wife was treated to the inelegant sounds of me cursing at my laptop screen for 10 or 15 minutes until I figured out what the problem was.</p>


<h3>&#8216;feed://&#8217; don&#8217;t go &#8217;round here</h3>

<p>The problem turmed out to be the &#8220;feed://&#8221; pseudo protocol.  Safari likes it (because it fancies itself a feed reader), and decided to make the <span class="caps">RSS </span>link provided by Google for the tag set my wife wanted to download into a &#8220;feed://&#8221; URL.  Of course, there&#8217;s no such protocol, and &#8220;feed://&#8221; itself is a pretty lame.  People have been <a href="http://www.rassoc.com/gregr/weblog/2003/09/15/subscriptions-with-feed/">bitching about its lameness</a> for a long, long time.  It&#8217;s almost as lame as me not catching it.</p>

<p>But the lamest thing of all (which was causing the cursing) is how OpenURI handles this:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">TypeError: can't convert Hash into String<br />
<br />
method initialize &nbsp; in open-uri.rb at line 32<br />
method open_uri_original_open &nbsp; in open-uri.rb at line 32<br />
method open in open-uri.rb at line 32<br />
method get&nbsp; in picasa.rb at line 62</div></td></tr></tbody></table></div>

<p>This is the same thing you get when you try to use <strong>open</strong> on a <span class="caps">URL </span>with a hash of header arguments and you&#8217;ve forgotten to require the OpenURI library in the first place.<br />
 <br />
The problem here seems to be with this part:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">def</span> <span class="kw3">open</span><span class="br0">&#40;</span>name, <span class="sy0">*</span>rest, <span class="sy0">&amp;</span>block<span class="br0">&#41;</span> <span class="co1"># :doc:</span><br />
&nbsp; <span class="kw1">if</span> name.<span class="me1">respond_to</span>?<span class="br0">&#40;</span><span class="re3">:open</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; name.<span class="kw3">open</span><span class="br0">&#40;</span><span class="sy0">*</span>rest, <span class="sy0">&amp;</span>block<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">elsif</span> name.<span class="me1">respond_to</span>?<span class="br0">&#40;</span><span class="re3">:to_str</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">%</span>r<span class="br0">&#123;</span>\A<span class="br0">&#91;</span>A<span class="sy0">-</span>Za<span class="sy0">-</span>z<span class="br0">&#93;</span><span class="br0">&#91;</span>A<span class="sy0">-</span>Za<span class="sy0">-</span>z0<span class="sy0">-</span><span class="nu0">9</span><span class="sy0">+</span>\<span class="sy0">-</span>\.<span class="br0">&#93;</span><span class="sy0">*</span>:<span class="sy0">//</span><span class="br0">&#125;</span> =~ name <span class="sy0">&amp;&amp;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>uri = <span class="kw4">URI</span>.<span class="me1">parse</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">respond_to</span>?<span class="br0">&#40;</span><span class="re3">:open</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; uri.<span class="kw3">open</span><span class="br0">&#40;</span><span class="sy0">*</span>rest, <span class="sy0">&amp;</span>block<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; open_uri_original_open<span class="br0">&#40;</span>name, <span class="sy0">*</span>rest, <span class="sy0">&amp;</span>block<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>It&#8217;s not calling the part you might think &#8212; the piece where it asks if the name can be converted to a string and if it conforms to a loose <span class="caps">URI </span>regex pattern.  It&#8217;s instead calling it with the original, version of <strong>open</strong>, the one that the Kernel class provides so you can easily open files and <span class="caps">URL</span>s (but without all the tasty options given you by OpenURI).  This error gets thrown by Kernel when you try to use open outside the context of OpenURI (as <a href="http://highearthorbit.com/open-uri-and-cant-convert-hash-into-string/">this guy points out</a>).</p>

<p>Since we can tell that a <span class="caps">URL </span>that starts with &#8220;feed://&#8221; should pass the first of the two tests in the &#8220;elsif&#8221; clause (the regex pattern), that means that it&#8217;s not passing some part of the the <span class="caps">URI.</span>parse test.  Here&#8217;s what that <span class="caps">URI.</span>parse method looks like:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">parse</span><span class="br0">&#40;</span>uri<span class="br0">&#41;</span><br />
&nbsp; scheme, userinfo, host, port, <br />
&nbsp; &nbsp; registry, path, opaque, query, fragment = <span class="kw2">self</span>.<span class="kw3">split</span><span class="br0">&#40;</span>uri<span class="br0">&#41;</span><br />
<br />
&nbsp; <span class="kw1">if</span> scheme <span class="sy0">&amp;&amp;</span> @@schemes.<span class="kw1">include</span>?<span class="br0">&#40;</span>scheme.<span class="me1">upcase</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; @@schemes<span class="br0">&#91;</span>scheme.<span class="me1">upcase</span><span class="br0">&#93;</span>.<span class="me1">new</span><span class="br0">&#40;</span>scheme, userinfo, host, port, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;registry, path, opaque, query, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fragment<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; Generic.<span class="me1">new</span><span class="br0">&#40;</span>scheme, userinfo, host, port, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; registry, path, opaque, query, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fragment<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>No great clues there.  But if you run through the code in the OpenURI#open method&#8217;s elsif clause, it turns out that if you parse the offending &#8220;feed://&#8221;-based <span class="caps">URI, </span>you don&#8217;t get a &#8220;URI::HTTP&#8221; object.  You get a &#8220;URI::Generic&#8221; object, which doesn&#8217;t respond to <strong>open</strong>.  Obviously, the library doesn&#8217;t support this kind of <span class="caps">URL, </span>and if it weren&#8217;t overriding a Kernel method, it&#8217;d probably say so, but it can&#8217;t make assumptions about what you&#8217;re trying to do with <strong>open</strong>, so it instead falls through to the call to the overridden Kernel#open and you get the same error you&#8217;d get if you never used &#8220;require &#8216;open-uri&#8217;&#8221; in the first place.</p>

<p>Lesson learned, boys and girls &#8212; pseudo protocols aren&#8217;t supported by much at all other than self-important feed reading software.</p>

<p><em>Thanks to the Gimite <a href="http://gimite.net/gimite/rubymess/google-spreadsheet-ruby/">Google Spreadsheet library</a> for inspiration on the auth code</em></p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/10/25/when-open-uri-cant-convert-hash-into-string-another-time-it-happens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make ruby-debug work better</title>
		<link>http://www.catapult-creative.com/2009/08/12/make-ruby-debug-work-better/</link>
		<comments>http://www.catapult-creative.com/2009/08/12/make-ruby-debug-work-better/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 16:18:50 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[remember-tip]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2009/08/12/end-some-of-the-pain-with-ruby-debug/</guid>
		<description><![CDATA[If you&#8217;ve written Ruby, chances are you&#8217;ve had to use ruby-debug.  You might&#8217;ve thought the experience sucked &#8212; especially the fact that the debugger defaults to a mode in which you have to use a keyword to get it to evaluate a statement.  Lost? Here&#8217;s what I mean:

Say you start the debugger here:

12result [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve written Ruby, chances are you&#8217;ve had to use <a href="http://rubyforge.org/projects/ruby-debug/">ruby-debug</a>.  You might&#8217;ve thought the experience sucked &#8212; especially the fact that the debugger defaults to a mode in which you have to use a keyword to get it to evaluate a statement.  Lost? Here&#8217;s what I mean:</p>

<p>Say you start the debugger here:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">result = resource[xml_obj.api_call_string].get<br />
(rdb:1)</div></td></tr></tbody></table></div>

<p>Then you want to take a look at the &#8220;xml_obj&#8221; variable.  If this were (for instance) <a href="http://docs.python.org/library/pdb.html">Python&#8217;s pdb</a>, we&#8217;d just type &#8220;xml_obj&#8221; and hit return and be done with it.  Not so in ruby-debug:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">(rdb:1) xml_obj.api_call_string<br />
*** Unknown command: &quot;xml_obj.api_call_string&quot;. &nbsp;Try &quot;help&quot;.</div></td></tr></tbody></table></div>

<p>This is because with default settings, the debugger needs a keyword (&#8217;p') to get it to actually evaluate your statement as Ruby and not a command to the debugger itself:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">(rdb:1) p xml_obj.api_call_string<br />
&quot;documentService/documentsByCommunity&quot;</div></td></tr></tbody></table></div>

<p>That gets really tedious, really fast.  The debugger&#8217;s help function (&#8217;help p&#8217;) will helpfully tell you that this is because the &#8220;autoeval&#8221; option is not enabled.  If you&#8217;re thick like me, you won&#8217;t see this and you&#8217;ll just continue doing &#8220;p &lt;whatever&gt;&#8221; until you get so frustrated you drop what you&#8217;re doing one day and go hunt down a fix.</p>

<p>Here is that fix from inside your code:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw3">require</span> <span class="st0">'ruby-debug'</span><br />
Debugger.<span class="me1">settings</span><span class="br0">&#91;</span><span class="re3">:autoeval</span><span class="br0">&#93;</span> = <span class="kw2">true</span></div></td></tr></tbody></table></div>

<p>You can also do this inside the debugger:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">(rdb:1) set autoeval<br />
autoeval is on.</div></td></tr></tbody></table></div>

<h3>Rails already does it via Rack middleware</h3>

<p>You might be wondering why the debugging experience is different in Rails than in Ruby you&#8217;ve written elsewhere.  I did too &#8212; remembering that this &#8216;p&#8217; business isn&#8217;t necessary when I run the debugger as an option when I start up Mongrel in a Rails app.  So I went digging for the code that Rails uses to set this stuff up.  Those settings come from a piece of Rack middleware that lives in <strong>lib/rails/rack/debugger.rb</strong>.  Here&#8217;s the class definition:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px;height:300px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">module</span> Rails<br />
&nbsp; <span class="kw1">module</span> Rack<br />
&nbsp; &nbsp; <span class="kw1">class</span> Debugger<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>app<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">@app</span> = app<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; require_library_or_gem <span class="st0">'ruby-debug'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ::Debugger.<span class="me1">start</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ::Debugger.<span class="me1">settings</span><span class="br0">&#91;</span><span class="re3">:autoeval</span><span class="br0">&#93;</span> = <span class="kw2">true</span> <span class="kw1">if</span> ::Debugger.<span class="me1">respond_to</span>?<span class="br0">&#40;</span><span class="re3">:settings</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">puts</span> <span class="st0">&quot;=&gt; Debugger enabled&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">rescue</span> <span class="kw4">Exception</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">puts</span> <span class="st0">&quot;You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">exit</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">def</span> call<span class="br0">&#40;</span>env<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">@app</span>.<span class="me1">call</span><span class="br0">&#40;</span>env<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>For more info on how Rails uses Rack, this is a pretty <a href="http://guides.rubyonrails.org/rails_on_rack.html">handy page</a> from the Rails guides.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/08/12/make-ruby-debug-work-better/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby XML Part 4 &#8211; Correction and Elucidation</title>
		<link>http://www.catapult-creative.com/2009/07/23/ruby-xml-part-4-correction-and-elucidation/</link>
		<comments>http://www.catapult-creative.com/2009/07/23/ruby-xml-part-4-correction-and-elucidation/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 11:48:24 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/?p=224</guid>
		<description><![CDATA[Hola amigos.  I know it&#8217;s been a long time since I rapped at you on my Ruby XML stuff, and some of these posts have been pretty dunce-tastic, so I know all my readers were looking forward with bated breath to the next installment, wherein I would no doubt prove that I had grown [...]]]></description>
			<content:encoded><![CDATA[<p>Hola amigos.  I know it&#8217;s been a long time since I rapped at you on my Ruby <span class="caps">XML </span>stuff, and some of these posts have been pretty dunce-tastic, so I know all my readers were looking forward with bated breath to the next installment, wherein I would no doubt prove that I had grown incrementally smarter.  Wait no longer.</p>

<p>OK so first things first.  This thing I&#8217;ve messed around with recently isn&#8217;t a <em>service</em> &#8212; it&#8217;s a <em>client</em>.  We must make sure that we get the nomenclature correct so that we&#8217;ll know what we&#8217;re all talking about.  The thing on the <strong>other end</strong> is the service.  I was referring to it as a service in kind of a generic way, but it wasn&#8217;t too helpful because this is most definitely properly called a client.</p>

<p>So what kinds of changes have I made recently?  Well first off, I decided that this snippet from my <a href="/2009/05/11/designing-a-rudimentary-xml-service-with-ruby-part-3/">last post</a> was just painful to the point of utter crappiness:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">w = <span class="re2">WebEx::Request</span>.<span class="me1">new</span><br />
w.<span class="me1">send_request</span><span class="br0">&#40;</span>XMLObject.<span class="me1">create_attendee</span><span class="br0">&#40;</span>@attendee<span class="br0">&#41;</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>Not only is it ugly, it&#8217;s long-winded and hard to remember.  As soon as I had another person working with this code at work, I felt the sting of shame and knew I had to re-factor.  I decided that there was no reason not to take the opportunity to use one of Ruby&#8217;s vaunted metaprogramming features to try and make this a little shorter.  Now it works like this:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">w = <span class="re2">WebEx::Request</span>.<span class="me1">new</span><br />
w.<span class="me1">create_attendee</span><span class="br0">&#40;</span>@attendee<span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<h3>Maybe #method_missing?</h3>

<p>So how did I accomplish that?  Simple, I used <a href="http://ruby-doc.org/core/classes/Kernel.html#M005925">Ruby&#8217;s method_missing</a> to enable arbitrary method calls to be made on the WebEx::Request object.</p>

<p><strong>method_missing</strong> is a hook method that gets called when there&#8217;s no definition found for a method called on an object &#8212; i.e. the method is missing.  When that happens, the Ruby interpreter automatically calls an instance method called method_missing.  Usually, that&#8217;s not defined, so the interpreter will raise an exception, but if method_missing <strong>is</strong> defined, the interpreter does whatever it says to.  Here, I&#8217;m defining it like this:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">def</span> method_missing<span class="br0">&#40;</span>request_method, <span class="sy0">*</span>args<span class="br0">&#41;</span><br />
&nbsp; <span class="kw2">self</span>.<span class="me1">send_request</span><span class="br0">&#40;</span><span class="re2">WebEx::XMLObject</span>.<span class="me1">send</span><span class="br0">&#40;</span>request_method.<span class="me1">to_sym</span>, <span class="sy0">*</span>args<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>In this case, <strong>self</strong> is of course an object of the WebEx::Request class.  When the interpreter tries to call #create_attendee on an instance of that class, it can&#8217;t find the method and method_missing is called.  My implementation of method_missing assumes that the &#8220;method&#8221; being called on the WebEx::Request object is a real class method of the <span class="caps">XMLO</span>bject class (which is where all my actual <span class="caps">API </span>calls are), so it calls it there, passing along the arguments it received in the first place.</p>

<p>Of course, if no such class method exists, the interpreter throws an exception like it should.  But for legitimate calls, I&#8217;ve shortened my code by quite a bit.</p>

<h3>&lt;gasp&gt; isn&#8217;t it bad to use method_missing?</h3>

<p>Some might argue that this is a cavalier usage of method_missing.  I don&#8217;t really think so.  The entirety of my request class is only like three methods other than this.  It exists only to make a request and process the result, but it does that dumbly because it actually uses <span class="caps">XMLO</span>bjects for the real meat of both.  WebEx::Request is just a dumb object acting on stuff at the direction of the WebEx::XMLObjects that it calls through <span class="caps">XMLO</span>bject class methods.  If the Request class had a lot more methods, using method_missing might have been an irresponsible design choice. But since the notion of the request and the <strong>thing being requested</strong> are necessarily intertwined, this approach made a lot of sense to me because it let me join the two classes up for usage (WebEx::Request and WebEx::XMLObject), improving readability and reducing verbosity but still letting me keep the two classes usefully separate in the code.</p>

<p><strong>method_missing</strong> is one of those things that you&#8217;ll sometimes hear people talking about Ruby referring to as magic.  Like <a href="http://gilesbowkett.blogspot.com/2009/07/do-you-believe-in-magic.html">other, more experienced folk</a>, I hate the usage of the word &#8220;magic&#8221; to describe things that happen in Ruby.  The concepts behind metaprogramming aren&#8217;t that difficult, and as Mr. Giles says in his blog post, metaprogramming is just programming.  If not for method_missing, you wouldn&#8217;t have cool stuff like <a href="http://builder.rubyforge.org/">Builder</a> and <a href="http://builder.rubyforge.org/">RSpec</a>.  Or maybe you would, but not as elegantly.  method_missing underlies much of the powerful <a href="http://en.wikipedia.org/wiki/Domain-specific_language">Doman-Specific Language</a> stuff that is so popular and useful in Ruby, so as my dad used to say: &#8220;it&#8217;s not bad or scary &#8212; it&#8217;s just different.&#8221;</p>

<p>(<a href="http://gist.github.com/152807">Gist of the full module</a>)</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/07/23/ruby-xml-part-4-correction-and-elucidation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing a Rudimentary XML Service with Ruby &#8212; (Part 3)</title>
		<link>http://www.catapult-creative.com/2009/05/11/designing-a-rudimentary-xml-service-with-ruby-part-3/</link>
		<comments>http://www.catapult-creative.com/2009/05/11/designing-a-rudimentary-xml-service-with-ruby-part-3/#comments</comments>
		<pubDate>Mon, 11 May 2009 19:05:00 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">tag:www.catapult-creative.com,2009-05-11:100</guid>
		<description><![CDATA[I&#8217;ve come full circle since part 1 in this mini-saga, and am now describing my simple WebEx XML web service with three classes in a WebEx module.

Ruby modules offer the programmer the ability to group classes together into like structures and to control namespaces for methods.  They also function as a sort of pseudo-class, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve come full circle since <a title="Designing a Rudimentary XML Service with Ruby" href="/2009/3/11/a-rudimentary-xml-service-with-ruby">part 1 in this mini-saga</a>, and am now describing my simple WebEx <span class="caps">XML </span>web service with three classes in a WebEx module.</p>

<p><a title="Class: Module" href="http://www.ruby-doc.org/core/classes/Module.html">Ruby modules</a> offer the programmer the ability to group classes together into like structures and to control namespaces for methods.  They also function as a sort of pseudo-class, in that you can define &#8220;module methods&#8221; inside the module that feel like class methods.  If you have a module <strong>Foo</strong> and a method <strong>self.bar</strong>, you can call it with <strong>Foo.bar</strong>.</p>

<p>That&#8217;s what I ended up doing with all the helper methods I&#8217;ve got in this new class definition &#8212; WebEx.time_from_string, WebEx.filter_by_session_name, etc.</p>

<p>I also abstracted the things I&#8217;d need into several classes.  Now the <span class="caps">XML </span>client has:</p>


<ul>
<li>An <strong>Attendee</strong> class to describe the most common type of <span class="caps">API </span>data we need to create and manipulate</li>
<li>An <strong><span class="caps">XMLO</span>bject</strong> class which describes a generic object containing <span class="caps">XML </span>and the recipe necessary to process it into Ruby data structures (implemented as a <a title="Class: Proc" href="http://www.ruby-doc.org/core/classes/Proc.html">Proc object</a>), as well as class methods for generating various types of such objects</li>
<li>A <strong>Request</strong> class which is responsible for sending an <span class="caps">XMLO</span>bject to the WebEX <span class="caps">API, </span>sending the retrieved data through the object&#8217;s processor, and exposing the processed data as well as the processed result strings from the <span class="caps">API </span>request.</li>
</ul>



<p>Here&#8217;s how you&#8217;d create an attendee (I&#8217;m stipulating the existence of an initialized Attendee object &#8212; @attendee)</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">w = <span class="re2">WebEx::Request</span>.<span class="me1">new</span><br />
w.<span class="me1">send_request</span><span class="br0">&#40;</span>XMLObject.<span class="me1">create_attendee</span><span class="br0">&#40;</span>@attendee<span class="br0">&#41;</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p><a title="WebEx module definition" href="http://gist.github.com/110113"><em>Gist of the new WebEx module</em></a></p>

<p>This is necessarily kind of a spare time project.  It&#8217;s something for work, but it does what it&#8217;s meant to just fine right now, so re-factoring it is something I&#8217;m doing in spare cycles.  However, I&#8217;m gratified that continued refactoring has brought me back to the original idea of having a simple class with class methods that mirror the <span class="caps">API&#8217;</span>s methods.  I had to trip through the things that brought me to make the other classes and gather everything together into a module, but it was a helpful (if stumbling) process to go through.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/05/11/designing-a-rudimentary-xml-service-with-ruby-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing a rudimentary XML Service with Ruby (Part 2)</title>
		<link>http://www.catapult-creative.com/2009/03/18/designing-a-rudimentary-xml-service-with-ruby-part-2/</link>
		<comments>http://www.catapult-creative.com/2009/03/18/designing-a-rudimentary-xml-service-with-ruby-part-2/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 17:28:00 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">tag:www.catapult-creative.com,2009-03-18:96</guid>
		<description><![CDATA[A few days back, I posted on my journey of understanding into the world of Ruby-based XML clients.  This post is a continuation of that account.

Re-Arranging the WebEx Class

I figured it wouldn&#8217;t be long before I was back at the drawing board on my main architecture, and I was right.  The earlier one [...]]]></description>
			<content:encoded><![CDATA[<p><em>A few days back, I posted on my <a title="catapult creative  Designing a Rudimentary XML Service with Ruby" href="http://www.catapult-creative.com/2009/3/11/a-rudimentary-xml-service-with-ruby">journey of understanding</a> into the world of Ruby-based <span class="caps">XML </span>clients.  This post is a continuation of that account.</em></p>

<h3>Re-Arranging the WebEx Class</h3>

<p>I figured it wouldn&#8217;t be long before I was back at the drawing board on my main architecture, and I was right.  The earlier one I described turned out to be over-abstracted and hard to test.</p>

<p>It all started with my feeling that this looks really elegant:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">events = WebEx.<span class="me1">request</span><span class="br0">&#40;</span>Event.<span class="me1">list</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>But in practice it turns out to be a little strange.  &#8220;Attendee&#8221; and &#8220;Event&#8221; were two classes with no attributes of their own, and none of my code ever instantiated objects of these classes.  These are two pretty obvious signs over an over-abstracted implementation.  I&#8217;d been thinking that I&#8217;d write logic later which would (for example) instantiate objects of the Event class inside Event.list&#8217;s processor, but as I got more and more into the implementation, it just didn&#8217;t seem like I was going to need to mess with WebEx&#8217;s return values as discreetly defined <strong>objects</strong>.  After all, I already had Events and Attendees represented as hashes in an array, which was working just fine for this first use case and the ones I could see on the horizon.  Having separate classes for Event and Attendee would give me maximum extensibility, but at the cost of having pieces of overlong, over-organized code with no (current) purpose.</p>

<p>So I moved the Event class&#8217;s code into the WebEx class.  Same with Attendee &#8212; now the WebEx class&#8217;s code looks like this:</p>

<p><em>(<a title="gist: 81268 - GitHub" href="http://gist.github.com/81268">Gist of the WebEx class</a>)</em></p>

<p>As you can see, everything is now an instance method of the WebEx object.  This means that the syntax for getting a list of Events is now:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">w = WebEx.<span class="me1">new</span><br />
events = w.<span class="me1">request</span><span class="br0">&#40;</span>w.<span class="me1">event_list</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>This still looks a little weird to me.  I had been thinking that I should make WebEx#request into a class method, so as to have:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">events = WebEx.<span class="me1">request</span><span class="br0">&#40;</span>w.<span class="me1">event_list</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>But that would mean having WebEx.request instantiate and return a new object of the WebEx class.  There&#8217;s nothing wrong with that, but given the fact that another WebEx object already needs to be created in order to call one of its instance methods (event_list), it felt like a case where two objects of the same class which weren&#8217;t being used at all in the same way.  Because of that awkwardness, I decided to live with the clunky-but-servicable all-instance-method approach.  After all &ndash; there&#8217;s a good chance that I&#8217;ll refactor it yet again as I go&#8230; :-p</p>

<h3>Testing</h3>

<p>I&#8217;m embarrassed to not have spotted this earlier: the class as it had been written before was very hard to test for a couple major reasons:</p>


<ul>
<li>There was no way to override the <span class="caps">XML </span>attribute of one of the WebExmlObjects being returned by class methods Event.list and Attendee.list_for_meeting</li></li>
<li>The <span class="caps">HTTP </span>request happened within the WebEx.request method, making it difficult to stub the <span class="caps">HTTP </span>request&#8217;s response, which had to happen in order to ensure that calling that method during testing didn&#8217;t involve net calls.</li>
</ul>




<p>I solved each of these easily enough: I abstracted the <span class="caps">HTTP </span>request into its own method and I added a &#8220;payload&#8221; argument to each method that returned a WebExmlObject so that I could override its request <span class="caps">XML.</span></p>

<p>After that, it was time to set up some fixtures.  I created directories for &#8220;request&#8221; and &#8220;response&#8221; in my fixtures dir and added files containing the well-formed <span class="caps">XML </span>samples I got from the WebEx docs.  Then I wrote methods for opening/reading each of them in my WebExSpecHelper module (this testing is all in <a title="RSpec-1.2.0: Home" href="http://rspec.info/">RSpec</a>).  Below is a test that ensures that WebEx#request is calling WebEx#request_post:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">it <span class="st0">&quot;should call request_post&quot;</span> <span class="kw1">do</span><br />
&nbsp; <span class="re1">@w</span>.<span class="me1">should_receive</span><span class="br0">&#40;</span><span class="re3">:request_post</span><span class="br0">&#41;</span>.<span class="me1">and_return</span><span class="br0">&#40;</span>lst_summary_event_response<span class="br0">&#41;</span><br />
&nbsp; <span class="re1">@w</span>.<span class="me1">request</span><span class="br0">&#40;</span>@w.<span class="me1">event_list</span><span class="br0">&#41;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p><strong>@w</strong> is the instance variable that is created before every spec, and <strong>lst_summary_event_response</strong> is the name of the spec helper method that returns the fixture of that <span class="caps">XML </span>response.  There&#8217;s no particular reason I called this one as opposed to an attendee-related method &ndash; I just needed to assert that the call would happen and then stipulate the response it would give, so any of my helper methods would do.</p>

<p>Here&#8217;s that helper method doing what it&#8217;s meant to:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">it <span class="st0">&quot;it should return all events if passed a nil time limit&quot;</span> <span class="kw1">do</span><br />
&nbsp; <span class="re1">@events</span> = <span class="re1">@w</span>.<span class="me1">event_list</span><span class="br0">&#40;</span>payload=lst_summary_event_request, time_limit=<span class="kw2">nil</span><span class="br0">&#41;</span>.<span class="me1">processor</span>.<span class="me1">call</span><span class="br0">&#40;</span>@w.<span class="me1">doc</span><span class="br0">&#41;</span><br />
&nbsp; <span class="re1">@events</span>.<span class="me1">length</span>.<span class="me1">should</span> be<span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>There are three events in the fixture, so the length should be three when nothing is passed to time limit.  All the fixture data from WebEx was in the past, so I altered the dates in there to have one event in the past, one in the future, and one in the future at a more distant date. Here&#8217;s what happens when you pass a time limit past that first (earlier) future date</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">it <span class="st0">&quot;should return only events happening after the time limit&quot;</span> <span class="kw1">do</span><br />
&nbsp; middle_future_date = <span class="st0">&quot;04/02/2012 01:06:49&quot;</span><br />
&nbsp; limit = <span class="re1">@w</span>.<span class="me1">time_from_string</span><span class="br0">&#40;</span>middle_future_date<span class="br0">&#41;</span><br />
&nbsp; <span class="re1">@events</span> = <span class="re1">@w</span>.<span class="me1">event_list</span><span class="br0">&#40;</span>payload=lst_summary_event_request, time_limit=limit<span class="br0">&#41;</span>.<span class="me1">processor</span>.<span class="me1">call</span><span class="br0">&#40;</span>@w.<span class="me1">doc</span><span class="br0">&#41;</span><br />
&nbsp; <span class="re1">@events</span>.<span class="me1">length</span>.<span class="me1">should</span> be<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Only one result gets returned, because the fixture only has one event listing which has a start date after the date given.</p>

<h3>Next Steps</h3>

<p>So far, my unit tests have covered very little &ndash; basically just the processor portion of a WebExmlObject.  For full coverage, I&#8217;ll need to test the <strong> <img src='http://www.catapult-creative.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml</strong> attribute which means validating the generated <span class="caps">XML </span>against the <span class="caps">XML</span> Schema Definitions(XSDs) WebEx provides with their <span class="caps">API </span>docs.  Ruby doesn&#8217;t provide have any all-native tools for doing validation of <span class="caps">XML </span>against a given <span class="caps">XSD, </span>but the <strong>libxml</strong> library (which is distributed as a gem and gets its power from C-bindings it compiles at install time) will let you pass in a schema as a string and then validate against it.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/03/18/designing-a-rudimentary-xml-service-with-ruby-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing a Rudimentary XML Service with Ruby</title>
		<link>http://www.catapult-creative.com/2009/03/11/designing-a-rudimentary-xml-service-with-ruby/</link>
		<comments>http://www.catapult-creative.com/2009/03/11/designing-a-rudimentary-xml-service-with-ruby/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 14:39:00 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">tag:www.catapult-creative.com,2009-03-11:95</guid>
		<description><![CDATA[1events = WebEx.request&#40;Event.list&#41;

That felt the most natural to me.  The idea is that you have a WebEx class that&#8217;s basically responsible for initiating the connection and handling the boilerplate security stuff that&#8217;s going to be at the top of any XML API request.  The question then became how to structure the Event class [...]]]></description>
			<content:encoded><![CDATA[<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">events = WebEx.<span class="me1">request</span><span class="br0">&#40;</span>Event.<span class="me1">list</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>That felt the most natural to me.  The idea is that you have a WebEx class that&#8217;s basically responsible for initiating the connection and handling the boilerplate security stuff that&#8217;s going to be at the top of any <span class="caps">XML API </span>request.  The question then became how to structure the Event class so that it could do two things at once: pass in the <span class="caps">XML </span>for the request and process the <span class="caps">XML </span>from the response.</p>

<h3>WebExmlObject and its Subclasses</h3>
<p>I decided to define a WebExmlObject class with &#8220;xml&#8221; and &#8220;processor&#8221; attributes:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">class</span> WebExmlObject<br />
&nbsp; attr_accessor <span class="re3">:xml</span>, <span class="re3">:processor</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Then I could define subclasses for each of the major types of objects I&#8217;d be pulling from WebEx (Attendee and Event, to start).  For right now, it doesn&#8217;t matter that the subclasses themselves don&#8217;t define any new attributes or instance methods &ndash; it&#8217;s worth it to me to do it this way because I believe that they probably will have to in the future.  And in any case, I&#8217;m a sucker for aesthetics and simplicity, and I wanted the readability and elegance you get from the class method approach I outlined above.  Here&#8217;s the Event class and its single class method:</p>

<p>(<a href="http://gist.github.com/77506" title="gist: 77506 - GitHub">Event class Gist</a>)</p>

<p>Notice that this method is basically in two halves: the first half creates the <span class="caps">XML </span>and the second creates the processor as a Proc object.  After creating the <span class="caps">XML </span>(using the super-handy <a href="http://builder.rubyforge.org/" title="Builder for Markup">Builder</a> library), I create a new Event object and load the <span class="caps">XML </span>into it.  Then I create a Proc and set it to the event object&#8217;s <strong>:processor</strong> attribute.  The processor assumes one argument will be passed to it &ndash; the <span class="caps">XML </span>response as a <span class="caps">REXML </span>document &ndash; and it returns an array of hashes, each one representing an event.  Only the stuff I care about is in each event hash, an easily extendable list represented by the <strong>event_keys</strong> variable.</p>

<h3>The WebEx Class</h3>
<p>Next up is the implementation of the request part.  The WebEx class has two instance methods: <strong>request</strong> and <strong>response</strong>.  <strong>Request</strong> takes a WebExmlObject, adds its <span class="caps">XML </span>in as the body of the request, makes the request, parses the response, and returns an object of class WebEx.  <strong>Response</strong> holds the response header.  Here&#8217;s the full implementation of the class:</p>

<p>(<a href="http://gist.github.com/77508" title="gist: 77508 - GitHub">WebEx class Gist</a>)</p>

<h3>Putting it Together</h3>
<p>I&#8217;m still working on the integration part of this, but it&#8217;s happening in <a href="http://www.sinatrarb.com/" title="Sinatra">Sinatra</a>, so I can easily show the short piece that renders the form:</p>

<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">get <span class="st0">'/online_demo'</span> <span class="kw1">do</span><br />
&nbsp; events = WebEx.<span class="me1">request</span><span class="br0">&#40;</span>Event.<span class="me1">list</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">if</span> events.<span class="me1">response</span><span class="br0">&#91;</span><span class="st0">'result'</span><span class="br0">&#93;</span> == <span class="st0">&quot;SUCCESS&quot;</span><br />
&nbsp; &nbsp; <span class="re1">@events</span> = events.<span class="me1">body</span><br />
&nbsp; &nbsp; erb <span class="re3">:online_demo</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; LOGGER.<span class="me1">warn</span><span class="br0">&#40;</span><span class="st0">'No meetings appear to be available at this time'</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>It&#8217;s obviously still a work in progress, but you can see how the <span class="caps">XML</span>-to-object abstraction feels pretty well hidden, and the class structure provides the level of elegance and terseness that I was hoping for.  If you&#8217;re unfamiliar with the way Sinatra works, the above is called when an <span class="caps">HTTP GET </span>request is made to the <span class="caps">URL </span>&#8220;&lt;WEBROOT&gt;/online_demo&#8221;.  Once the request is made and parsed into the <strong>events</strong> variable, I create the <strong>@events</strong> instance variable to hold the actual events array. The last thing I do is call the ERb template &#8220;online_demo&#8221;.  Instance variables created in this block are available to the template in much the same way as the controller/view relationship works in Rails.  The view is responsible for iterating over the array and inserting the proper attributes into the proper places:</p>

<div class="codecolorer-container html4strict blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="html4strict codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="sc2">&lt;<a href="http://december.com/html/4/element/label.html"><span class="kw2">label</span></a> <span class="kw3">for</span><span class="sy0">=</span><span class="st0">&quot;demo_startdate&quot;</span>&gt;</span>Choose a demo date:<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/label.html"><span class="kw2">label</span></a>&gt;</span><br />
&nbsp; <span class="sc2">&lt;<a href="http://december.com/html/4/element/select.html"><span class="kw2">select</span></a> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;sessionKey&quot;</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;demo-startdate&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<a href="http://december.com/html/4/element/option.html"><span class="kw2">option</span></a> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;&quot;</span>&gt;</span>Please select<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/option.html"><span class="kw2">option</span></a>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;% @events.each do |event| %&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<a href="http://december.com/html/4/element/option.html"><span class="kw2">option</span></a> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">&quot;&lt;%= event['sessionKey'] %&gt;</span></span>&quot;&gt;<span class="sc2">&lt;%<span class="sy0">=</span> event<span class="br0">&#91;</span><span class="st0">'startDate'</span><span class="br0">&#93;</span> %&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/option.html"><span class="kw2">option</span></a>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;% end %&gt;</span><br />
&nbsp; <span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/select.html"><span class="kw2">select</span></a>&gt;</span></div></td></tr></tbody></table></div>

<p>I&#8217;ll post more about this as I move forward, just to document the process of learning how to structure this stuff.  I&#8217;m still not entirely satisfied with the semantics of the WebEx class&#8217;s methods &ndash; especially since calling <strong>request</strong> will set up your object with the data you need and  <strong>response</strong> only gives you access to the header of the response.  I pacify myself by reasoning that since one is a class method and one is an instance method, there&#8217;s no philosophical/structural problem, but something about it still bugs me.</p>

<p>Big thanks to bona fide code wizard <a href="http://www.nimbletechnique.com/blog" title="Nimble Technique -">Collin VanDyck</a> for suggestions in this process &ndash; as always, I&#8217;m proud to be able to call <span class="caps">CCV </span>my homie.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/03/11/designing-a-rudimentary-xml-service-with-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Profile your Rails RSpec and find your slow tests fast</title>
		<link>http://www.catapult-creative.com/2008/07/18/profile-your-rails-rspec-and-find-your-slow-tests-fast/</link>
		<comments>http://www.catapult-creative.com/2008/07/18/profile-your-rails-rspec-and-find-your-slow-tests-fast/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 17:08:00 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[remember-tip]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">tag:www.catapult-creative.com,2008-07-18:69</guid>
		<description><![CDATA[Long-as-hell Ruby on Rails RSpec test running times are making you ask &#8220;what the deuce?&#8221;  Specs are taking way too long to run, but the prospect of looking through them all one at a time to find offending external dependencies, net calls that should be mocked, etc is driving you to drink. You just [...]]]></description>
			<content:encoded><![CDATA[<p>Long-as-hell Ruby on Rails RSpec test running times are making you ask &#8220;what the deuce?&#8221;  Specs are taking way too long to run, but the prospect of looking through them all one at a time to find offending external dependencies, net calls that should be mocked, etc is driving you to drink. You just want a read-out of the tests that are taking the longest so you can refactor <span class="caps">ASAP.</span></p>

<p>Sound familiar?</p>

<p>I was in this boat until I found out about the profiling command:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$&gt;spec spec -f profile</div></td></tr></tbody></table></div>

<p>The double &#8220;spec&#8221; here can be a bit confusing.  The first is the command, and the second is the directory (RAILS_ROOT/spec) that you&#8217;re running it on.  The -f is the format flag.  You can see a list of all formats with:</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:620px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$&gt;spec --help</div></td></tr></tbody></table></div>

<p>Basically you&#8217;re just passing the &#8220;profile&#8221; argument to the formatting command.  It gives you a readout of the 10 most time-intensive specs at the top and then a nicely verbose list of all pending and failed tests.  Using this list, I was able to go straight to the most obnoxious offenders and eliminate the external dependencies (these specs happened to be fetching feeds) that were slowing my test suite down.  In less than 15 minutes, I had chopped my execution time down to 10% of what it was before I started.</p>

<p>Huzzah!</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2008/07/18/profile-your-rails-rspec-and-find-your-slow-tests-fast/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autotester and GrowlGlue &#8211; an adventurer is me!</title>
		<link>http://www.catapult-creative.com/2008/07/13/autotester-and-growlglue-an-adventurer-is-me/</link>
		<comments>http://www.catapult-creative.com/2008/07/13/autotester-and-growlglue-an-adventurer-is-me/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 03:49:00 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">tag:www.catapult-creative.com,2008-07-14:66</guid>
		<description><![CDATA[Setting up autotest earlier today was kind of an annoying, semi-humbling experience.  A few things that people should know to save themselves some trouble:


  Everyone calls it autotest, but it&#8217;s actually ZenTest that you need to install.  ZenTest is a larger testing package, of which autotest is merely one part.

  Autotest [...]]]></description>
			<content:encoded><![CDATA[<p>Setting up <a href="http://www.zenspider.com/ZSS/Products/ZenTest/" title="ZenTest: Automated test scaffolding for Ruby">autotest</a> earlier today was kind of an annoying, semi-humbling experience.  A few things that people should know to save themselves some trouble:</p>

<ul>
  <li>Everyone calls it autotest, but it&#8217;s actually <a href="http://www.zenspider.com/ZSS/Products/ZenTest/" title="ZenTest: Automated test scaffolding for Ruby">ZenTest</a> that you need to install.  ZenTest is a larger testing package, of which autotest is merely one part.</li>

  <li>Autotest runs as a separate process (which you should background &mdash; the &#8216;&amp;&#8217; is your friend!) and watches your Rails dir <em>after you have it turned on</em>.  This last bit took me some time to figure out, as the otherwise excellent <a href="http://peepcode.com/products/rspec-basics" title="RSpec Basics | PeepCode Screencasts for Ruby on Rails Developers">RSpec Peepcode screencast</a> completely glosses over this point.  I kept waiting for the magic to happen when I hit &#8220;save&#8221; in TextMate, but I didn&#8217;t have the process running from the command line.  Magic doesn&#8217;t work.  I should stop expecting it to.</li>

  <li>Do yourself a favor and vastly simplify your autotest&#8211;&gt;Growl connection by using Collin VanDyck&#8217;s <a href="http://gluedtomyseat.com/2008/7/9/growl-glue-tying-together-autotest-and-growl" title="gluedtomyseat: GrowlGlue : tying together Autotest and Growl">GrowlGlue gem</a> as the basis for your .autotest config file.</li>
</ul>

<p>As of right now, I&#8217;m sitting here with just the <a href="http://growl-glue.rubyforge.org/" title="growl-glue-1.0.1 Documentation">basic GG config</a>.  I&#8217;m sure I&#8217;ll expand/customize tomorrow, but I&#8217;m just happy for now that I was able to get a working setup with just one line of code, as the normal way to get the connection going involves a <a href="http://blog.aisleten.com/2008/02/21/installing-growlnotify-and-autotest-for-bdd-use-with-rspec-on-leopard/" title="Midnight Oil  &amp;raquo; Blog Archive   &amp;raquo; Installing GrowlNotify and Autotest for BDD use with Rspec on Leopard">decent amount of crap</a>.  After you get that going, GrowlGlue lets you set up all sorts of customization of the notifications &mdash;  including custom messages, custom notification icons, and even speaking your test results through OS X&#8217;s built-in text-to-speech support &mdash; in nice, neat Ruby statements.</p>

<p>It&#8217;s nice to have something get in my face about my tests, and it&#8217;s also nice to have something that automatically makes you want to get your tests passing and running <em>faster</em>.  Autotest provides you with the nagging voice that says &#8220;get your tests running right, holmes!&#8221;  It&#8217;s good to strike this longstanding to-do off my list.</p>

<p><em>Late update:</em> Turns out that running autotest in the background isn&#8217;t really ideal since you might sometimes want to cancel a running suite or check out the time elapsed since you started a given test set.  What I&#8217;m looking for now is a way to see how long it takes any <em>individual</em> test to run so that I can find the offenders that are kicking up the aggregate time.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2008/07/13/autotester-and-growlglue-an-adventurer-is-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
