<?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; Rails</title>
	<atom:link href="http://www.catapult-creative.com/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.catapult-creative.com</link>
	<description>worldwide (web) whatnot</description>
	<lastBuildDate>Fri, 17 Jun 2011 00:45:29 +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>Creating an admin area in Rails</title>
		<link>http://www.catapult-creative.com/2010/08/18/creating-an-admin-area-in-rails/</link>
		<comments>http://www.catapult-creative.com/2010/08/18/creating-an-admin-area-in-rails/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 13:24:33 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2010/08/18/creating-an-admin-area-in-rails/</guid>
		<description><![CDATA[This is an answer I posted to a question on Stack Overflow.  The title of that question is a little off from what the writer actually wanted to know, so I decided to to re-post the answer here.  It&#8217;s a bit of an easy/basic topic, but it comes up a lot, so I [...]]]></description>
			<content:encoded><![CDATA[<p><em>This is <a href="http://stackoverflow.com/questions/3502436/understanding-mvc-architecture-as-non-mvc-developer/">an answer I posted to a question on Stack Overflow</a>.  The title of that question is a little off from what the writer actually wanted to know, so I decided to to re-post the answer here.  It&#8217;s a bit of an easy/basic topic, but it comes up a lot, so I thought other people out there might find it useful.</em></p>

<p>The two things to keep in mind when making an admin area are </p>


<ol>
<li>you can create namespaces for routes to get the /admin <span class="caps">URL</span>s you&#8217;re looking for and </li>
<li>you can have controllers inherit from other descendants of ActionController</li>
</ol>



<p>So to make an admin area, you&#8217;d want to have <span class="caps">REST</span>ful resources declared in a namespace (assumes Rails 3 routes):</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="co1"># routes.rb</span><br />
resources <span class="re3">:users</span><br />
resources <span class="re3">:posts</span><br />
resources <span class="re3">:pages</span><br />
<br />
namespace <span class="re3">:admin</span> <span class="kw1">do</span> <span class="sy0">|</span>admin<span class="sy0">|</span><br />
&nbsp; match <span class="st0">'/'</span> <span class="sy0">=&gt;</span> <span class="st0">'dashboard#index'</span><br />
&nbsp; resources <span class="re3">:users</span><br />
&nbsp; resources <span class="re3">:posts</span><br />
&nbsp; resources <span class="re3">:pages</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>The top set is the public ones and the bottom set gives you the admin routes like /admin/users/new and /admin/posts/1, etc.  I&#8217;m also assuming you might want a &#8220;dashboard&#8221; so I&#8217;m setting up a route to the index method of an Admin::DashboardController</p>

<p>Then you create an admin base controller that descends from ApplicationController.  Use it to hold your admin area layout and your authentication filters:</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"><span class="kw1">class</span> <span class="re2">Admin::BaseController</span> <span class="sy0">&lt;</span> ApplicationController<br />
&nbsp; before_filter <span class="re3">:require_user</span><br />
&nbsp; layout <span class="st0">'admin'</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Now make a directory in app/controllers called &#8220;admin&#8221;. Make controllers in there as normal, but have them inherit from your base controller:</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"><span class="co1"># pages_controller.rb</span><br />
<span class="kw1">class</span> <span class="re2">Admin::PagesController</span> <span class="sy0">&lt;</span> <span class="re2">Admin::BaseController</span><br />
&nbsp; <span class="co1"># Controller code in here</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Make a corresponding directory in app/views for &#8220;admin&#8221; and you&#8217;re good to go &#8212; everything is namespaced out and views/controllers would behave like you think.</p>

<p>You can always run &#8220;rake routes&#8221; to see all the admin routes.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2010/08/18/creating-an-admin-area-in-rails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bundler is totally worth the hype</title>
		<link>http://www.catapult-creative.com/2010/07/29/bundler-is-totally-worth-the-hype/</link>
		<comments>http://www.catapult-creative.com/2010/07/29/bundler-is-totally-worth-the-hype/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 03:36:03 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2010/07/29/bundler-is-totally-worth-the-hype/</guid>
		<description><![CDATA[Let us all now sing a hymn of praise to Bundler.  You know, like even more than we already were.  Not that it needs too much more light shining on it, what with being a dependency to Rails and all, but I&#8217;ve had cause in the past few days to throw up my [...]]]></description>
			<content:encoded><![CDATA[<p>Let us all now sing a hymn of praise to <a href="http://gembundler.com/">Bundler</a>.  You know, like even more than we already were.  Not that it needs too much more light shining on it, what with being a dependency to Rails and all, but I&#8217;ve had cause in the past few days to throw up my hands and make a joyful noise.</p>

<p>Now is a piece of software designed to do something as prosaic as dependency management going to get you hot and bothered all by itself?  Probably not.  It&#8217;s not going to be like when you discovered the beauty of <a href="http://ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html">Ruby&#8217;s iterators</a>, or how to get the QBasic interpreter to give you the <a href="http://videosift.com/video/Qbasic-Gorillas-video-game">exploding banana game</a> in <span class="caps">MSDOS</span> 5.x+.  </p>

<p>But along those same lines, Bundler will help you reserve more of your mental compute cycles for things that matter and fill you with wonder, secure in the knowledge that you&#8217;ve chopped off a few big boulders from the pile of computational entropy constantly threatening to avalanche everyone in our industry into oblivion.</p>

<p>Examples:</p>

<h3>Kids should come with &#8220;bundle install&#8221;.</h3>

<p>Apps are complicated because you need all sorts of specific stuff to deal with them.  That&#8217;s why Bundler was originally invented, obviously.  But real-world scenarios are always valuable, and today I had to get a development version of the app I&#8217;m building for my main client running on the designer&#8217;s machine, and do it as fast as possible.  While the designer is good w/ <span class="caps">HTML</span>/CSS, she doesn&#8217;t know thing one about Rails, rubygems, or the <span class="caps">RVM</span>-based sequestering of different Ruby versions, etc (another hymn another time for <span class="caps">RVM</span>).  I got all that going for her, and then, with a mere two commands (one of which checked out the source code from the repo and therefore didn&#8217;t really even count), I bootstrapped the entire app at once, while surfing the web.  &#8220;bundle install&#8221; for the win.  That same process would&#8217;ve taken me (just for the app&#8217;s dependencies) about 45 minutes or so in previous incarnations of Rails.  This way, it took less than three.  And almost all of that was completely automated.</p>

<h3>Specifying refs is a thing of beauty</h3>

<p>Rails 3 rc1 came out a couple days ago.  Like every other RoR cultist, I upgraded as soon as I heard.  A bunch of crap promptly broke.  Those wacky core team members!  They love to make a boatload of commits on something and then call it a release candidate, just to keep us all sharp.</p>

<p>One of the things that broke was <a href="http://github.com/pluginaweek/state_machine">state_machine</a>, which I rely on extensively in this the aforementioned app.  So one upgrade from Rails 3b4 to Rails 3rc1 and I&#8217;m sitting there in a puddle of my own tears, with all my specs broken and no ability to run my seeds.rb file.</p>

<p>Thankfully, the gem maintainer rapidly came up with a patch.  But he didn&#8217;t have a release ready yet.  So what did I do?  In the old days, I&#8217;d have to download his code at that Git reference and then put together a new gem on my own, keeping a vendored version that was seperate from the other versions of the gem I might&#8217;ve been using, etc etc.  I&#8217;m sure there&#8217;s probably a better way to do it even under the old regime, but with Bundler, you simply pass in a reference to the commit where it&#8217;s been fixed!</p>

<p>So 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 /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">gem <span class="st0">'state_machine'</span>, <span class="re3">:git</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;git://github.com/pluginaweek/state_machine.git&quot;</span></div></td></tr></tbody></table></div>

<p>Becomes 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 /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">gem <span class="st0">'state_machine'</span>, <span class="re3">:git</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;git://github.com/pluginaweek/state_machine.git&quot;</span>, <span class="re3">:ref</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;1e5e04bb67be0b504a5fe9ca10a490286825d452&quot;</span></div></td></tr></tbody></table></div>

<p>That blew my mind even more than the dead-simple bootstrapping of my colleague&#8217;s development system.  For working with libraries that are still in frequent development, and for fixing things like the myriad breakages that can occur when one version jumps up to be something else, this is a godsend.</p>

<p>So don&#8217;t bitch about Bundler, even if you&#8217;re tempted to in the beginning.  Like everything else surrounding Ruby/Rails, it&#8217;s new and it takes some getting used to.  But in the end, you&#8217;re likely to love it, and to wonder how you ever got along without it.  Plus, this gives us yet another reason to laugh at Pythonistas, who still lack even a Rubygems equivalent.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2010/07/29/bundler-is-totally-worth-the-hype/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open Source and Amazon: concrete examples of empowerment for iPhone apps</title>
		<link>http://www.catapult-creative.com/2010/03/25/open-source-and-amazon-concrete-examples-of-empowerment-for-iphone-apps/</link>
		<comments>http://www.catapult-creative.com/2010/03/25/open-source-and-amazon-concrete-examples-of-empowerment-for-iphone-apps/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 14:34:14 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2010/03/25/httpriot-iphone-with-rails/</guid>
		<description><![CDATA[I&#8217;ve posted exactly zero times in the last two months because I&#8217;m head-down like a mad man, working with my team to get our very first iPhone app ready for shipping.  Fingers are crossed that this will happen in about a month or so, and I have to say that so far 2010 has [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve posted exactly zero times in the last two months because I&#8217;m head-down like a mad man, working with my team to get our very first iPhone app ready for shipping.  Fingers are crossed that this will happen in about a month or so, and I have to say that so far 2010 has been a whirlwind education in the creation of iPhone software and the server backends who love it.  That means that so far I&#8217;ve had no time to learn about the wonders of <a href="http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/">Rails 3</a>, or to pontificate at length on <a href="http://www.huffingtonpost.com/2010/03/21/health-care-bill-passes-l_n_507714.html">the healthcare bill</a>, or to beat <a href="http://masseffect.bioware.com/">Mass Effect 2</a>.</p>

<p>But I have had time to be impressed, once again, at the awesome power of open source and the game-changing nature of <a href="http://aws.amazon.com/">Amazon Web Services</a>.</p>

<h3>Open Source &#8212; <span class="caps">HTTP</span>riot and delayed_job</h3>

<p>Without going into too much detail, the iPhone app I&#8217;m working on (codenamed &#8220;Pedro&#8221;) records audio files and uploads them to a server.  Naturally I&#8217;m using Rails for the backend, so I needed something to help me communicate easily with the server.  After trying both an <a href="http://allseeing-i.com/ASIHTTPRequest/"><span class="caps">ASIHTTP</span>request</a>  with <a href="http://www.grinninglizard.com/tinyxml/">TinyXML</a> solution and <a href="http://iphoneonrails.com/">Objective Resource</a>, I eventually settled on <a href="http://alternateidea.com/blog/articles/2009/7/11/introducing-httpriot-easily-consume-rest-resources-on-the-iphone-and-os-x"><span class="caps">HTTP</span>riot</a>.  <span class="caps">HTTP</span>riot is a Goldilocks solution.  <span class="caps">ASI</span>/Tiny are just too cumbersome since you end up having to write parsing methods yourself (and really, who the hell wants to do that when the entire point of structured serialization formats is that something should be able to turn them into native data structures (hashes/dictionaries) for you?), and ObjectiveResource seemed to do just a little too much and to rely on <a href="http://macdevelopertips.com/objective-c/objective-c-categories.html">Objective-C categories</a> a bit much for my comfort.</p>

<p><span class="caps">HTTP</span>riot sits right between these solutions and is <em>just right</em> (had to complete the Goldilocks thought) for talking to <span class="caps">REST </span>services <span class="caps">IMO. </span> You serialize something out as an <span class="caps">NSD</span>ictionary and <span class="caps">POST </span>or <span class="caps">PUT </span>it to the server, and you get back a response you can treat as a dictionary.  <span class="caps">GET </span>requests are a one-liner (though to do it right you need a few methods so you can have a ViewController delegate handle the eventual response).  The only drawback I&#8217;ve found so far to <span class="caps">HTTP</span>riot is that it requires you to cram all your processing logic for any given resource into a single method, as one and only one delegate method handles a successful server response.  But that&#8217;s a small gripe.  Using this excellent library, I was able to re-write the entire <span class="caps">ASI</span>/Tiny solution in a few hours.  That&#8217;s versus a few days getting it set up in the first place.  If you need to talk to a <span class="caps">REST </span>service with an iPhone, I highly recommend <span class="caps">HTTP</span>riot.  As a bonus, the inimitable Geoffrey Grossenbach (@topfunky) uses it in <a href="https://peepcode.com/products/iphone-view-controllers-part-i">one of Peepcode&#8217;s iPhone screencasts</a>, enabling you to get both a step-by-step tutorial on creating a non-trivial working application with <span class="caps">HTTP</span>riot, and a good bit of explanation on how the library ought to be used.</p>

<p>When <span class="caps">HTTP</span>riot is done pushing an audio file to my app server, a <a href="http://github.com/collectiveidea/delayed_job">Ruby library called delayed_job</a> does the background processing required to send it to <a href="http://aws.amazon.com/s3/">Amazon S3</a>, where it will live and respond to <span class="caps">GET </span>requests via <a href="http://aws.amazon.com/cloudfront/">Amazon Cloudfront</a>.  delayed_job was created by the redoubtable Rubyists behind <a href="http://www.shopify.com/">Shopify</a>, the coolest turnkey e-commerce solution I&#8217;ve found so far.  I&#8217;ve made a site or two for clients using Shopify, so I was excited to discover that they&#8217;d opened up the library they wrote to do background processing.  delayed_job is a database-backed persistent job queue that runs in its own process and makes backgrounding a task dead simple.  You can do all sorts of fancy things with prioritization and whatnot, but the thing that made me fall in love (even though my use cases eventually got a bit too complex to use it very much) is the fact that you can run any method with <strong>send_later</strong> &#8212; as in:</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">foo_object.<span class="me1">send_later</span><span class="br0">&#40;</span><span class="re3">:process_that_takes_awhile</span>, <span class="re1">@argument</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>

<p>That one-liner will bop it into the queue, and delayed_job will handle it as it can.  It&#8217;s really that easy.  I&#8217;m using dj for sending emails and pushing binary files to Amazon, but I might start using it for other things as well.  <a href="http://www.engineyard.com/">EngineYard</a> (where we&#8217;re hosting this opus) supports it for production, and for development, you get a nice Rake task to help you manage it and keep an eye on the tasks as they happen.</p>

<p>The point of all this exposition is to say that I feel fortunate to have come up as a code dunce during a time in which open source software is mature enough to be able to provide even a relative n00b like me with documented, real-world-tested, helpful stuff that does exactly what I need it to &#8212; whether on the server side or on the client side.  It&#8217;s worth mentioning as well that both of these things are arguably direct offshoots of the Rails community (delayed_job is in Ruby and was built to serve a Rails app, and <span class="caps">HTTP</span>riot was built with <span class="caps">REST </span>interactions in mind, which Rails has done a lot to help popularize), which continues to astound me in its breadth, creativity, and helpfulness.</p>

<h3><span class="caps">AWS </span>&#8211; cheaper than dirt, more valuable than gold</h3>

<p>Have you ever seen anything as <strong>cheap</strong> as the stuff offered by Amazon Web Services?  I don&#8217;t think I have.  Or to put it more directly, <span class="caps">AWS </span>are the cheapest things I&#8217;ve ever seen someone try to put a price tag on:</p>

<p>- <a href="http://aws.amazon.com/s3/"><strong>S3</strong></a>, Amazon&#8217;s storage service, charges $.015 per GB for the first 10 TB of transfer bandwidth you use in a month.  And the prices go down from there.  Get out your calculator and do the math to see how much data you have to be moving around before this starts to cost you more than you have in your change jar, and you&#8217;ll likely spend 20 minutes or so cackling to yourself about just how inexpensive mind-blowing web power is these days.</p>

<p>- <a href="http://aws.amazon.com/cloudfront/"><strong>Cloudfront</strong></a>, Amazon&#8217;s <span class="caps">CDN </span>charges $.01 for every 10,000 <span class="caps">GET </span>requests.  Do the calculator thing on that one (realizing that it&#8217;s basically an add-on to the above), and you&#8217;ll be laughing even longer.</p>

<p>- We buy <a href="http://aws.amazon.com/ec2/"><strong><span class="caps">EC2</span></strong></a>, Amazon&#8217;s scalable-on-demand computing service, through a reseller (EngineYard) who really doesn&#8217;t add all that much to the $0.085/hour cost that Amazon themselves charge.  EngineYard is able to offer hosting solutions optimized for Rails based on <span class="caps">EC2, </span>along with monitoring and Rails-oriented deployment and management tools, for so little extra on top of what Amazon themselves charge that for the first few weeks you&#8217;ll feel like you&#8217;re getting away with a crime.</p>

<p>Without the open source libraries I mentioned above, Pedro would take much, much longer to build and would be necessarily a bit less stable, simply because my team and I would be building everything from scratch.  But without Amazon Web Services, there&#8217;s no way we could even entertain the notion of making this app.  Pedro is a game: a funny, 99-cent App Store novelty that we hope will go viral and make us some cash.  Apple gives us a great way to distribute the app, but without Amazon, we&#8217;d have show-stopping cost barriers to actually building a backend capable of meeting rapid, viral demand.  A few years ago, just standing up unused production infrastructure to handle these use cases would&#8217;ve cost us thousands of dollars a month in rents, to say nothing of what it would cost in time and/or people-hours to have a qualified sysadmin lurking on our payroll.  Now because of Amazon, those barriers are gone &#8212; replaced by a giggle-inducing cost structure for computing resources that back one of the most powerful retailer/supply chains on Earth.</p>

<p>With the preponderance of open source libraries and the rise of commoditized enterprise-scale computing, the utopia really <em>is</em> now &#8212; the only things holding anyone back are time, creativity, and will.</p>

<p>Speaking of which, I need to dive back down my code hole.  See you in a month or so.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2010/03/25/open-source-and-amazon-concrete-examples-of-empowerment-for-iphone-apps/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>Moving to jQuery from RJS: Getting Started</title>
		<link>http://www.catapult-creative.com/2009/06/07/rocking-jquery-with-rails/</link>
		<comments>http://www.catapult-creative.com/2009/06/07/rocking-jquery-with-rails/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 18:07:28 +0000</pubDate>
		<dc:creator>Trevor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CodeDunce]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.catapult-creative.com/2009/06/07/rocking-jquery-with-rails/</guid>
		<description><![CDATA[Props to this guy&#8217;s post.  

Some parts are kind of confusing, but it&#8217;s a testatment to how much code he posts that I didn&#8217;t even realize he was French until I sat down to write this post and read it more carefully &#8212; he communicated mostly in code.

He gives a good Rails application.js file [...]]]></description>
			<content:encoded><![CDATA[<p>Props to <a href="http://www.notgeeklycorrect.com/english/2009/05/18/beginners-guide-to-jquery-ruby-on-rails/">this guy&#8217;s post</a>.  </p>

<p>Some parts are kind of confusing, but it&#8217;s a testatment to how much code he posts that I didn&#8217;t even realize he was French until I sat down to write this post and read it more carefully &#8212; he communicated mostly in code.</p>

<p>He gives a good <a href="http://gist.github.com/110410">Rails application.js file</a> for you to start out with &#8212; basically it provides a bunch of handles for things you want to remote w/ <span class="caps">XHR. </span> They use the new-ish <a href="http://docs.jquery.com/Events/unbind#typefn">jQuery method unbind</a> to make sure that regular events on items designated as <span class="caps">AJAX </span>get overriden.  Pretty slick and a good way to think of jQuery&#8217;s usage in an app context.  So far, I hadn&#8217;t really used it for <span class="caps">AJAX </span>beyond a thing I wrote to enable cross-domain MX record validation.</p>

<h3>Example: remote links</h3>

<p>Rails provides the <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html#M001613">link_to_remote</a> helper to let you create links that will trigger a <span class="caps">GET </span>over <span class="caps">XHR. </span> This application.js defines a jQuery function for that and then binds it to a certain class of links &#8212; &#8220;get&#8221;:</p>

<div class="codecolorer-container javascript 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 /></div></td><td><div class="javascript codecolorer" style="font-family:Monaco,Lucida Console,monospace">jQuery.<span class="me1">fn</span>.<span class="me1">getWithAjax</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">unbind</span><span class="br0">&#40;</span><span class="st0">'click'</span><span class="sy0">,</span> <span class="kw2">false</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">click</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; $.<span class="me1">get</span><span class="br0">&#40;</span>$<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">attr</span><span class="br0">&#40;</span><span class="st0">&quot;href&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> $<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">serialize</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw2">null</span><span class="sy0">,</span> <span class="st0">&quot;script&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">this</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><span class="sy0">;</span></div></td></tr></tbody></table></div>

<p>Which is then set with this:</p>

<div class="codecolorer-container javascript 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="javascript codecolorer" style="font-family:Monaco,Lucida Console,monospace">$<span class="br0">&#40;</span><span class="st0">'a.get'</span><span class="br0">&#41;</span>.<span class="me1">getWithAjax</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></td></tr></tbody></table></div>

<p>Now any anchor with class &#8220;get&#8221; on it will result in a remote call to the <span class="caps">URL </span>in that anchor&#8217;s href.  Combined with a respond_to block in your controller to handle Javascript and a Javascript template file, you can use links like this to (for instance) load ActiveRecord objects into a page using <span class="caps">AJAX.</span> Instead of &#8220;show.erb.html&#8221; your controller&#8217;s show method is handled by &#8220;show.js.erb&#8221;.  This block in the show method of the controller ensures that it is activated correctly:</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">respond_to <span class="kw1">do</span> <span class="sy0">|</span>format<span class="sy0">|</span><br />
&nbsp; <span class="kw3">format</span>.<span class="me1">html</span><br />
&nbsp; <span class="kw3">format</span>.<span class="me1">js</span> <span class="br0">&#123;</span> render <span class="re3">:layout</span> <span class="sy0">=&gt;</span> <span class="kw2">false</span> <span class="br0">&#125;</span><br />
<span class="kw1">end</span></div></td></tr></tbody></table></div>

<p>Because the call came in over <span class="caps">XHR, </span>the controller sees the format as being JS and responds with the instructions set in the block passed to format.js.  Rendering without layout ensures that nothing but the rendered data plus the template is returned.</p>

<p>Notice that the <span class="caps">AJAX </span>call in the above snippet from application.js uses the &#8220;script&#8221; datatype.  This specifies that the returned data should be evaluated as Javascript, which is what we want, because the returned data includes the jQuery-based instructions we have inside show.js.erb, and those need to get <em>evaluated</em> (not just displayed) in order for the page to look right.</p>

<p>An aside: One thing that this makes me think about a lot is how important visual design is when you&#8217;re developing an application.  Your design has to correspond concretely to a <span class="caps">DOM </span>with all sorts of manipulative handles (ids and classes) and all sorts of custom functions built to do various things to/with them.  You&#8217;d damn well better draw a decent picture of this and give the elements of it some good names that make sense.  In fact, I think a lot of the true work in programming involves drawing pictures (I still model some embarrassingly simple relationships with pencil and paper), but that might just be the way that my brain works.</p>

<p>Anywho, I took the above application.js and used it as the basis for a conversion from <span class="caps">RJS </span>to jQuery in a Rails app I&#8217;m working on.  I&#8217;ll probably end up adding quite a bit to his stuff as I go, but having this file around made starting the transition process a lot easier.</p>

<p>I expect to do some more posts on the conversion as I go, since I haven&#8217;t found a whole lot of stuff yet that&#8217;s oriented toward &#8220;strategies for using jQuery with Rails&#8221; and wasn&#8217;t written in 2007.  <span class="caps">RJS </span>kept me from dealing w/ JS directly as a major component of my app, but those days are over now that I&#8217;m committed to unobtrusive JS via jQuery, and a more thought-out approach will be necessary.</p>]]></content:encoded>
			<wfw:commentRss>http://www.catapult-creative.com/2009/06/07/rocking-jquery-with-rails/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>

